Pretransplant natural antibody levels identify a subset of deceased donor kidney transplant recipients that benefit from infliximab induction
Statistical report
Authors and affiliations
Vojtech Petr1,2, Samuel L. Liu3, Filip Tichanek1, Felix Poppelaars2, Brandon Renner2, Jennifer Laskowski2, Shrey Purohit2, Ming Zhao3, Diana Jalal4,5, Peter S. Heeger6,#, Joshua M. Thurman3,#
1 Institute for Clinical and Experimental Medicine, Prague, Czech Republic
2 Department of Medicine, University of Colorado School of Medicine, Anschutz Medical Campus, Aurora, CO, USA
3 Feinberg Cardiovascular and Renal Research Institute, Northwestern University, Chicago, IL, USA
4 Department of Medicine, Carver College of Medicine, University of Iowa, IA, USA
5 Iowa City VA HCS, Iowa City, IA, USA
6 Departments of Medicine, Surgery and Biomedical Sciences, Cedars Sinai Medical Center, Los Angeles, CA, USA
# Co-senior authors, contributed equally
This is a statistical report of the study titled Pretransplant natural antibody levels identify a subset of deceased donor kidney transplant recipients that benefit from infliximab induction currently under review in the American Journal of Transplantation journal.
When using this code or data, cite the original publication:
TO BE ADDED
BibTex citation for the original publication:
TO BE ADDED
Original GitHub repository: https://github.com/filip-tichanek/infliximab_nAb
Statistical reports can be found here
1 Manuscript text
1.1 Statistical analysis methods
1.1.1 Full version
Analyses were performed in R (version 4.4.2) (R Core Team 2024) and GraphPad Prism (version 10.2.3). Continuous variables are reported as medians with interquartile ranges and categorical variables as counts and percentages. Group comparisons were conducted using the Mann–Whitney test, and correlations were assessed via Spearman’s rank correlation.
Unadjusted effects of covariates (including nAb and their interaction with infliximab) were estimated using complete-case logistic regression for binary outcomes (DGF, infection, and BKV infection) and linear models for eGFR.
For outcome–nAb combinations where the 95% confidence interval of the interaction term did not include the null effect, we fit multivariable Bayesian models with a non-linear interaction between log\(_2\)-transformed nAb levels and infliximab using penalized B-splines with 5 knots (separately for each treatment group). Logistic Bayesian regression was used for binary outcomes, while Bayesian robust regression (Student’s t-distribution) was used for eGFR. Covariates were prespecified based on their well-documented association with kidney transplant outcomes and included donor and recipient sex, HLA mismatch count, KDPI, perfusion event, recipient age, and cold ischemia time.
Missing data (35 for HLA mismatch, 21 for perfusion event, 3 for cold ischemia time) were handled via multiple imputation (80 datasets) using the ‘mice’ package (van Buuren and Groothuis-Oudshoorn 2011). Binary variables were imputed via logistic regression, and numeric variables via predictive mean matching. Bayesian models were run using the ‘brms’ package (Bürkner 2017) with Hamiltonian Monte Carlo sampling (4 chains, 2000 iterations including 1900 warm-ups per each of 80 imputed datasets, yielding 32,000 post-warmup samples). Posterior distributions were summarized by the median (point estimate) and the 2.5th and 97.5th percentiles (95% credible interval, 95% CrI).
Priors for fixed effects were Gaussian, centered at 0 (\(\mu = 0\)), with \(\sigma\) defined as follows:
In logistic model (binary outcomes):
\(\sigma = 4\) for binary predictors
\(\sigma = \frac{2}{\text{SD}(\text{predictor})}\) for numeric predictors
For robust regression (eGFR):
\(\sigma = 4 \times \text{SD}(\text{eGFR})\) for binary predictors
\(\sigma = \frac{2 \times \text{SD}(\text{eGFR})}{\text{SD}(\text{predictor})}\) for numeric predictors
Non-linear effects used Student’s t priors:
Baseline spline: \(df = 3, \mu = 0, \sigma = 0.6\)
Treatment-specific spline: \(df = 3, \mu = 0, \sigma = 0.3\)
Posterior estimates for infliximab effects were obtained at the 5th, 25th, 50th, 75th, and 95th percentiles of nAb levels. We quantified the modulation of infliximab treatment by comparing the posterior distributions of the treatment effect at the 5th and 95th percentiles of nAb levels. For each posterior sample, we computed the ratio of odds ratios (OR at 95th percentile / OR at 5th percentile) in logistic models and the difference in treatment effects (\(\beta_{\text{infliximab}}|\text{nAbs}=95^\text{th}\) – \(\beta_{\text{infliximab}}|\text{nAbs}=5^\text{th}\)) in robust regression for eGFR.
Mediation analysis was performed using the ‘bayestestR’ package (Makowski, Ben-Shachar, and Lüdecke 2019) to assess whether infliximab affected eGFR and whether this effect was mediated through DGF. Analyses were conducted separately for individuals with below- and above-median aCL IgG levels.
Because the highest aCL IgG levels were only observed in the control group, we performed a sensitivity analysis by restricting the dataset to patients with aCL IgG levels within the range observed in the infliximab group.
1.1.2 Short version (manuscript)
All analyses were conducted in R (version 4.4.2) and GraphPad Prism (version 10.2.3). Continuous variables are reported as medians with interquartile ranges, and categorical variables as percentages. Spearman’s rank correlation assessed associations.
Unadjusted analyses used logistic regression for binary outcomes (DGF, infection, and BKV infection) and linear models for eGFR, both based on complete cases. When the 95% confidence interval of the interaction term between nAb and infliximab did not include the null effect, multivariable Bayesian models with non-linear interactions (using group-specific B splines) were fitted to using the ‘brms’ R package. These models employed logistic regression for binary outcomes and robust (Student’s t) regression for eGFR, with multiple imputation (80 datasets) for missing data.
Pre-specified covariates included donor and recipient sex, HLA mismatch count, KDPI, perfusion event, recipient age, and cold ischemia time. Posterior distributions were summarized by medians with 95% credible intervals (CrI). To evaluate infliximab treatment effects across different nAb levels, we obtained posterior distributions at the 5th, 25th, 50th, 75th, and 95th percentiles of these levels. To quantify how strongly nAb levels modulate the infliximab effect, we compared infliximab estimates at the 95th and 5th percentiles, reporting the ratio of odds ratios for binary outcomes and the difference in treatment effects for eGFR.
Bayesian mediation analysis (using ‘bayestestR’) was used to assess whether infliximab’s effect on eGFR is mediated through DGF, stratified by above- vs. below-median aCL IgG levels. A sensitivity analysis was performed by restricting the dataset to patients with aCL IgG levels within the range observed in the infliximab group.
A full description of the statistical modeling methods, including prior specifications and posterior sampling details, is provided in the Supplementary Methods and online with the code (https://filip-tichanek.github.io/infliximab_nAb).
1.2 Results
1.2.1 Data Distributions and nAB levels correlations
The distribution of antibody levels across different groups, defined by treatment group and either DGF (aCL) or infection (aPE), is shown in Figure 1. The figure indicates substantial variability in nAB levels and suggests differences across groups.
No correlation was found between IgG levels of aCL and aPE (Supplementary Figure 1). In contrast, IgM antibodies exhibited strong positive correlations among each other, correlations between IgM and IgG of the same epitope (e.g., aCL IgG and aCL IgM) were weaker. Altogether, this suggests that IgG aCL and aPE antibodies serve different purposes and reflect distinct immune responses of individual subjects.
1.2.2 aCL level mediates infliximab effect on DGF risk
Univariable logistic regression suggests that DGF risk may be associated with male recipient sex, HLA mismatch, cold ischemia time, and also infliximab:aCL IgG interaction (Supplementary Table 1), indicating that aCL may modulate the effect of infliximab on DGF risk.
To further explore this possible modulation, we fit a multivariable Bayesian logistic model allowing a non-linear relationship between aCL and DGF risk separately for each treatment group (Table 1). The results are in line with the unadjusted findings: the effect of infliximab varies with aCL IgG level, with the odds ratio for infliximab estimated to be 47 times larger (95% CrI: 4.4 to 610) in patients at the 5th percentile of aCL IgG level (0.29 µg/ml) versus those at the 95th percentile (5.78 µg/ml). Specifically, infliximab is expected to reduce the odds of DGF by 87% for those at the 5th percentile (OR: 0.13, 95% CrI: 0.03 to 0.49, Figure 2), whereas at the 95th percentile (5.78 µg/ml), the odds ratio reverses direction (OR: 6.24, 95% CrI: 1.38 to 30.32).
When we excluded patients in the control group with aCL levels higher than the maximum observed in the infliximab group, results remained consistent (Supplementary Figure 2). A similar pattern is observed for IgM, though the modulation effect is weaker (Supplementary Figure 3, Table 1). Subgroup analysis based on aCL IgG levels \(< median\) or \(\geq median\) also shows a similar pattern: infliximab reduces DGF risk at those with relatively low aCL IgG (OR: 0.21, 95% CrI: 0.06 to 0.64) but exhibits the opposite effect when aCL IgG \(\geq median\) (OR: 2.9, 95% CrI: 1.01 to 8.7).
In short, infliximab very likely reduces DGF risk when aCL is low but tends to increase it with relatively high aCL.
1.2.3 aCL mediates infliximab effect on eGFR
Univariable linear models suggested that eGFR may be associated with low KDPI, absence of DGF, and absence of perfusion event, as well as with the infliximab:aCL IgG interaction (Supplementary Table 2).
A subsequent Bayesian linear model shows a congruent result: infliximab is associated with a small negative to possibly large positive effect on eGFR for patients at the 5th percentile of aCL IgG (β: 7.7, 95% CrI: -2.4 to 17.9) but has likely negative effect at the 95th percentile (β: -17.4, 95% CrI: -30 to -5.1; Table 1; Supplementary Figure 2). Similar patterns emerge for aCL IgM (Supplementary Figure 4) and when excluding control patients whose aCL IgG exceeded the maximum level observed in the infliximab group (Supplementary Figure 5).
In unadjusted analysis, DGF was a strong predictor of eGFR. Since infliximab reduces DGF risk at low aCL but worsens it at high aCL, we tested whether aCL might modulate infliximab’s effect on eGFR via DGF. In patients with aCL below the median, Bayesian mediation analysis showed a positive indirect effect of infliximab on eGFR through reduced DGF risk (ACME: 5.4, 95% CrI: 1.6 to 10.6) and no clear direct effect (ACD: 2.1, 95% CrI: -6.1 to 10.1; Supplementary Table 3). By contrast, for aCL ≥ median, infliximab had a direct negative effect on eGFR (ADE: -11.1, 95% CrI: -19.1 to -2.9) with possible contribution with indirect negative effect via incressing DGF risk (ACME: -2.3, 95% CrI: -6.6 to 0.3).
In conclusion, infliximab may have positive indirect effect on eGFR via reducing DGF risk when aCL is low, but it likely decreases eGFR directly in patients with relatively high aCL.
1.2.4 aPE modulates infliximab effect on infection
Univariable logistic regression showed that infection risk was associated with KDPI and, surprisingly, negatively associated with longer cold ischemia time. There was also an interaction between infliximab and aPE, particularly with co-factor independent aPE (though less clearly with co-factor dependent aPE; Supplementary Table 4).
A Bayesian logistic model allowing a non-linear interaction between infliximab and co-factor independent aPE confirmed that infliximab likely increases infection risk at lower aPE levels (5th and 25th percentiles) but has an uncertain or possibly positive effect at higher levels (Supplementary Figure 6, Table 1). A similar pattern emerged for co-factor dependent aPE IgG (Supplementary Figure 7, Table 1).
Overall, these results suggest infliximab may raise infection risk, especially for patients with relatively low aPE levels.
1.2.5 Infliximab effects on BK viremia risk
Univariable logistic regression suggested that BKV infection risk is generally increased with infliximab, and there was no indication of effect modification by nAB level (Supplementary Table 5).
2 Initiation
Packages
Open code
if (TRUE) {rm(list = ls() )}
if (TRUE) {
suppressWarnings(suppressMessages({
library(tidyverse)
library(stringr)
library(stringi)
library(ggpubr)
library(emmeans)
library(gtsummary)
library(skimr)
library(car)
library(RJDBC)
library(sjPlot)
library(flextable)
library(openxlsx)
library(mgcv)
library(pROC)
library(cowplot)
library(boot)
library(glmnet)
library(brms)
library(projpred)
library(janitor)
library(arm)
library(corrplot)
library(lubridate)
library(kableExtra)
library(ggdist)
library(bayesplot)
library(coxed)
library(quantreg)
library(ggbeeswarm)
library(mgcv)
library(mice)
library(MASS)
library(bayestestR)
# Functions clashes
select <- dplyr::select
rename <- dplyr::rename
mutate <- dplyr::mutate
recode <- dplyr::recode
summarize <- dplyr::summarize
count <- dplyr::count
# Simple math functions
logit <-function(x){log(x/(1-x))}
inv_logit <- function(x){exp(x)/(1+exp(x))}
}))
}Functions
Open code
run <- function(expr, path, reuse = TRUE) {
fit <- NULL
if (reuse) {
path <- paste0(path, ".Rds")
fit <- suppressWarnings(try(readRDS(path), silent = TRUE))
if (inherits(fit, "try-error")) {
fit <- NULL
}
}
if (is.null(fit)) {
fit <- eval(substitute(expr))
if (reuse && !is.null(path) && nzchar(path)) {
saveRDS(fit, file = path)
}
}
return(fit)
}Setting seeds and scipen
Open code
set.seed(2025)
options(scipen = 999)3 Data
Upload data a create relevant variables
Open code
data2 <- read.xlsx(
"gitignore/data/dataset_updated_4_2024.xlsx")
data2 <- data2 %>%
mutate(
GPE_dep_log2 = log2(GPE_dep),
MPE_dep_log2 = log2(MPE_dep),
GPE_ind_log2 = log2(GPE_ind),
MPE_ind_log2 = log2(MPE_ind)
) %>%
mutate(
GPL_BC_log2 = log2(GPL_BC),
MPL_BC_log2 = log2(MPL_BC)
) %>%
mutate(CIT = CIT / 60) %>%
mutate(treatment_group = if_else(
infliximab == 1, "infiximab", "placebo"
))
summary(data2)
## ID_subject TNFR1_stain TNFR2_stain available flow
## Min. : 1001 Min. :0.000 Min. :0.0000 Min. :1 Min. :1
## 1st Qu.: 5017 1st Qu.:1.000 1st Qu.:0.0000 1st Qu.:1 1st Qu.:1
## Median : 8057 Median :2.000 Median :0.0000 Median :1 Median :1
## Mean :17827 Mean :1.667 Mean :0.1667 Mean :1 Mean :1
## 3rd Qu.:23007 3rd Qu.:2.000 3rd Qu.:0.0000 3rd Qu.:1 3rd Qu.:1
## Max. :57019 Max. :2.000 Max. :2.0000 Max. :1 Max. :1
## NA's :156 NA's :156 NA's :137
## ID_sample GPL MPL GPL_BC
## Length:180 Min. : 0.1270 Min. : 0.7469 Min. : 0.06879
## Class :character 1st Qu.: 0.6315 1st Qu.: 2.3548 1st Qu.: 0.60473
## Mode :character Median : 0.9434 Median : 4.1302 Median : 0.93076
## Mean : 1.9069 Mean : 6.7417 Mean : 1.91444
## 3rd Qu.: 1.7415 3rd Qu.: 7.4118 3rd Qu.: 1.79043
## Max. :30.7573 Max. :41.3703 Max. :30.90609
##
## MPL_BC GPE_ind MPE_ind GPE_dep
## Min. : 0.0216 Min. :0.0685 Min. :0.06700 Min. :0.0800
## 1st Qu.: 2.1391 1st Qu.:0.0940 1st Qu.:0.09175 1st Qu.:0.1565
## Median : 4.0818 Median :0.1115 Median :0.11250 Median :0.1905
## Mean : 6.6395 Mean :0.1569 Mean :0.13474 Mean :0.2316
## 3rd Qu.: 7.7745 3rd Qu.:0.1527 3rd Qu.:0.15375 3rd Qu.:0.2492
## Max. :42.7197 Max. :0.9775 Max. :0.67250 Max. :1.3345
## NA's :1 NA's :1 NA's :1
## MPE_dep flow_IgM flow_IgG infliximab
## Min. :0.0820 Min. : 87937 Min. : 46682 Min. :0.0000
## 1st Qu.:0.1310 1st Qu.:172979 1st Qu.: 60076 1st Qu.:0.0000
## Median :0.1820 Median :241051 Median : 74844 Median :0.0000
## Mean :0.2127 Mean :284641 Mean : 76880 Mean :0.4944
## 3rd Qu.:0.2505 3rd Qu.:359260 3rd Qu.: 88576 3rd Qu.:1.0000
## Max. :1.0415 Max. :713000 Max. :174621 Max. :1.0000
## NA's :1 NA's :137 NA's :137
## male_sex rec_age race_2 race_1
## Min. :0.0000 Min. :27 Min. :0.0000 Length:180
## 1st Qu.:0.0000 1st Qu.:45 1st Qu.:0.0000 Class :character
## Median :1.0000 Median :54 Median :0.0000 Mode :character
## Mean :0.6167 Mean :53 Mean :0.4111
## 3rd Qu.:1.0000 3rd Qu.:61 3rd Qu.:1.0000
## Max. :1.0000 Max. :73 Max. :1.0000
##
## ethnicity CKD_cause_1 CKD_cause_2 RRT_preTx
## Length:180 Length:180 Min. :1.000 Min. :0.0000
## Class :character Class :character 1st Qu.:1.750 1st Qu.:1.0000
## Mode :character Mode :character Median :3.000 Median :1.0000
## Mean :2.556 Mean :0.9167
## 3rd Qu.:3.000 3rd Qu.:1.0000
## Max. :5.000 Max. :1.0000
##
## RRT_months RRT_type dc_graftloss_event_24mo
## Min. : 2.00 Min. :0.0000 Min. :0.00000
## 1st Qu.: 36.00 1st Qu.:1.0000 1st Qu.:0.00000
## Median : 62.00 Median :1.0000 Median :0.00000
## Mean : 73.55 Mean :0.8121 Mean :0.03333
## 3rd Qu.: 96.00 3rd Qu.:1.0000 3rd Qu.:0.00000
## Max. :288.00 Max. :1.0000 Max. :1.00000
## NA's :15 NA's :15
## dc_graftloss_time_24mo male_sex_donor age_donor race_donor_2
## Min. : 0.0 Min. :0.00 Min. : 4.0 Min. :0.0000
## 1st Qu.:730.0 1st Qu.:0.00 1st Qu.:31.5 1st Qu.:0.0000
## Median :730.0 Median :1.00 Median :42.0 Median :1.0000
## Mean :652.7 Mean :0.55 Mean :40.3 Mean :0.6167
## 3rd Qu.:730.0 3rd Qu.:1.00 3rd Qu.:50.0 3rd Qu.:1.0000
## Max. :730.0 Max. :1.00 Max. :69.0 Max. :1.0000
## NA's :1
## race_donor_1 ethnicity_donor donor_cause_broad donor_cause_narrow
## Length:180 Length:180 Length:180 Length:180
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## donor_cause_anoxia donor_cause_CVA donor_type ATG
## Min. :0.0000 Min. :0.0000 Min. :0.00 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.75 1st Qu.:1.0000
## Median :0.0000 Median :0.0000 Median :1.00 Median :1.0000
## Mean :0.4556 Mean :0.2389 Mean :0.75 Mean :0.9944
## 3rd Qu.:1.0000 3rd Qu.:0.0000 3rd Qu.:1.00 3rd Qu.:1.0000
## Max. :1.0000 Max. :1.0000 Max. :1.00 Max. :1.0000
##
## maintenance_1 standard_triple HLA_MM HLAMMGE3 EBV_IgG
## Length:180 Min. :0.0000 Min. :0.000 Min. :0.00 Min. :1
## Class :character 1st Qu.:1.0000 1st Qu.:4.000 1st Qu.:1.00 1st Qu.:1
## Mode :character Median :1.0000 Median :5.000 Median :1.00 Median :1
## Mean :0.8889 Mean :4.368 Mean :0.85 Mean :1
## 3rd Qu.:1.0000 3rd Qu.:5.000 3rd Qu.:1.00 3rd Qu.:1
## Max. :1.0000 Max. :6.000 Max. :1.00 Max. :1
## NA's :36
## CMV_IgG_rec CMV_IgG_donor CMV_mismatch CMV_mismatch_orig
## Min. :0.0000 Min. :0.0000 Min. :0.0000 Length:180
## 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.0000 Class :character
## Median :1.0000 Median :1.0000 Median :0.0000 Mode :character
## Mean :0.6611 Mean :0.5754 Mean :0.1899
## 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:0.0000
## Max. :1.0000 Max. :1.0000 Max. :1.0000
## NA's :1 NA's :1
## blood_group_rec blood_group_donor DRH KDPI
## Length:180 Length:180 Length:180 Min. :20.00
## Class :character Class :character Class :character 1st Qu.:36.75
## Mode :character Mode :character Mode :character Median :53.00
## Mean :53.73
## 3rd Qu.:71.25
## Max. :93.00
##
## WIT CIT perfusion_event perfusion_time
## Min. : 0.00 Min. : 3.267 Min. :0.0000 Min. : 2.0
## 1st Qu.: 27.00 1st Qu.:10.267 1st Qu.:0.0000 1st Qu.: 8.0
## Median : 33.00 Median :15.367 Median :0.0000 Median :11.0
## Mean : 37.02 Mean :15.922 Mean :0.3962 Mean :11.3
## 3rd Qu.: 42.00 3rd Qu.:20.550 3rd Qu.:1.0000 3rd Qu.:15.0
## Max. :209.00 Max. :50.133 Max. :1.0000 Max. :19.0
## NA's :7 NA's :3 NA's :21 NA's :147
## resistance_index TCMR_6mo_event TCMR_6mo_time TCMRB_6mo_event
## Min. :0.0000 Min. :0.00000 Min. : 63.0 Min. :0.0000
## 1st Qu.:0.1500 1st Qu.:0.00000 1st Qu.:180.0 1st Qu.:0.0000
## Median :0.2050 Median :0.00000 Median :180.0 Median :0.0000
## Mean :0.2125 Mean :0.04386 Mean :175.3 Mean :0.1754
## 3rd Qu.:0.2525 3rd Qu.:0.00000 3rd Qu.:180.0 3rd Qu.:0.0000
## Max. :0.7000 Max. :1.00000 Max. :180.0 Max. :1.0000
## NA's :132 NA's :66 NA's :66 NA's :66
## TCMRB_6mo_time TCMR_24mo_event TCMR_24mo_time TCMRB_24mo_event
## Min. : 11.0 Min. :0.00000 Min. : 63 Min. :0.0000
## 1st Qu.:180.0 1st Qu.:0.00000 1st Qu.:730 1st Qu.:0.0000
## Median :180.0 Median :0.00000 Median :730 Median :0.0000
## Mean :161.6 Mean :0.08943 Mean :645 Mean :0.2764
## 3rd Qu.:180.0 3rd Qu.:0.00000 3rd Qu.:730 3rd Qu.:1.0000
## Max. :183.0 Max. :1.00000 Max. :730 Max. :1.0000
## NA's :66 NA's :57 NA's :57 NA's :57
## TCMRB_24mo_time AMR_6mo_event AMR_6mo_time AMR_24mo_event
## Min. : 11.0 Min. :0.00000 Min. : 41.0 Min. :0.00000
## 1st Qu.:370.5 1st Qu.:0.00000 1st Qu.:180.0 1st Qu.:0.00000
## Median :730.0 Median :0.00000 Median :180.0 Median :0.00000
## Mean :559.0 Mean :0.02632 Mean :175.9 Mean :0.05691
## 3rd Qu.:730.0 3rd Qu.:0.00000 3rd Qu.:180.0 3rd Qu.:0.00000
## Max. :749.0 Max. :1.00000 Max. :180.0 Max. :1.00000
## NA's :57 NA's :66 NA's :66 NA's :57
## AMR_24mo_time rejection_6mo_central rejectionB_6mo_central
## Min. : 41 Min. :0.00000 Min. :0.00000
## 1st Qu.:730 1st Qu.:0.00000 1st Qu.:0.00000
## Median :730 Median :0.00000 Median :0.00000
## Mean :668 Mean :0.02703 Mean :0.07207
## 3rd Qu.:730 3rd Qu.:0.00000 3rd Qu.:0.00000
## Max. :738 Max. :1.00000 Max. :1.00000
## NA's :57 NA's :69 NA's :69
## rejection_24mo_central rejectionB_24mo_central CKD_EPI_3_vs_24
## Min. :0.00000 Min. :0.0000 Min. :-35.490
## 1st Qu.:0.00000 1st Qu.:0.0000 1st Qu.: -3.800
## Median :0.00000 Median :0.0000 Median : 1.330
## Mean :0.03361 Mean :0.1092 Mean : 3.256
## 3rd Qu.:0.00000 3rd Qu.:0.0000 3rd Qu.: 12.520
## Max. :1.00000 Max. :1.0000 Max. : 50.760
## NA's :61 NA's :61 NA's :91
## CKD_EPI_6_vs_24 DGF CRR_day_2 CRR_below_30_day_2
## Min. :-35.810 Min. :0.00 Min. :-24.200 Min. :0.0000
## 1st Qu.: -3.250 1st Qu.:0.00 1st Qu.: 5.688 1st Qu.:0.0000
## Median : 2.805 Median :0.00 Median : 21.650 Median :1.0000
## Mean : 2.925 Mean :0.35 Mean : 19.867 Mean :0.6842
## 3rd Qu.: 10.967 3rd Qu.:1.00 3rd Qu.: 33.292 3rd Qu.:1.0000
## Max. : 38.160 Max. :1.00 Max. : 60.870 Max. :1.0000
## NA's :94 NA's :66 NA's :66
## CRR_day_5 CRR_below_70_day_5 preformed_DSA de_novo_DSA
## Min. :-43.44 Min. :0.0000 Min. :0.00000 Min. :0.0000
## 1st Qu.: 30.08 1st Qu.:1.0000 1st Qu.:0.00000 1st Qu.:0.0000
## Median : 47.32 Median :1.0000 Median :0.00000 Median :0.0000
## Mean : 42.78 Mean :0.8333 Mean :0.02809 Mean :0.0618
## 3rd Qu.: 63.48 3rd Qu.:1.0000 3rd Qu.:0.00000 3rd Qu.:0.0000
## Max. : 84.22 Max. :1.0000 Max. :1.00000 Max. :1.0000
## NA's :66 NA's :66 NA's :2 NA's :2
## infection_any infection_wo_BKV infection_with_BKV infection_with_BKV_2
## Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.0000
## Median :0.0000 Median :0.0000 Median :1.0000 Median :1.0000
## Mean :0.4278 Mean :0.3056 Mean :0.5222 Mean :0.5222
## 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:1.0000
## Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.0000
##
## BKV_event_2 BKV_viremia_event BKV_viremia_time terminated_event
## Min. :0.0000 Min. :0.0000 Min. : 0.0 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.: 188.8 1st Qu.:0.0000
## Median :0.0000 Median :0.0000 Median : 735.0 Median :0.0000
## Mean :0.2167 Mean :0.2167 Mean : 684.0 Mean :0.1889
## 3rd Qu.:0.0000 3rd Qu.:0.0000 3rd Qu.: 939.2 3rd Qu.:0.0000
## Max. :1.0000 Max. :1.0000 Max. :1854.0 Max. :1.0000
##
## terminated_days death_event death_date death_time
## Min. : 0.0 Min. :0.00000 Min. :43181 Min. : 6.0
## 1st Qu.: 121.2 1st Qu.:0.00000 1st Qu.:43370 1st Qu.:295.0
## Median : 258.5 Median :0.00000 Median :43425 Median :421.0
## Mean : 373.4 Mean :0.03333 Mean :43428 Mean :376.3
## 3rd Qu.: 561.2 3rd Qu.:0.00000 3rd Qu.:43552 3rd Qu.:518.5
## Max. :1323.0 Max. :1.00000 Max. :43591 Max. :606.0
## NA's :146 NA's :174 NA's :174
## death_time_730 death_cause death_24mo GFR_days
## Min. : 0.0 Length:180 Min. :0.00000 Min. : 26.0
## 1st Qu.:730.0 Class :character 1st Qu.:0.00000 1st Qu.:369.2
## Median :730.0 Mode :character Median :0.00000 Median :692.5
## Mean :656.8 Mean :0.03333 Mean :542.4
## 3rd Qu.:730.0 3rd Qu.:0.00000 3rd Qu.:740.8
## Max. :730.0 Max. :1.00000 Max. :919.0
## NA's :2
## GFR_MDRD GFR_CKD GPE_dep_log2 MPE_dep_log2
## Min. : 8.44 Min. : 8.88 Min. :-3.6439 Min. :-3.60823
## 1st Qu.: 39.08 1st Qu.: 38.17 1st Qu.:-2.6758 1st Qu.:-2.93237
## Median : 50.00 Median : 51.65 Median :-2.3921 Median :-2.45799
## Mean : 51.91 Mean : 54.26 Mean :-2.2846 Mean :-2.40078
## 3rd Qu.: 64.56 3rd Qu.: 66.01 3rd Qu.:-2.0043 3rd Qu.:-1.99712
## Max. :123.48 Max. :106.01 Max. : 0.4163 Max. : 0.05866
## NA's :2 NA's :2 NA's :1 NA's :1
## GPE_ind_log2 MPE_ind_log2 GPL_BC_log2 MPL_BC_log2
## Min. :-3.86775 Min. :-3.8997 Min. :-3.8616 Min. :-5.533
## 1st Qu.:-3.41120 1st Qu.:-3.4462 1st Qu.:-0.7257 1st Qu.: 1.097
## Median :-3.16488 Median :-3.1520 Median :-0.1035 Median : 2.029
## Mean :-2.92959 Mean :-3.0281 Mean : 0.1137 Mean : 1.999
## 3rd Qu.:-2.71076 3rd Qu.:-2.7013 3rd Qu.: 0.8403 3rd Qu.: 2.958
## Max. :-0.03283 Max. :-0.5724 Max. : 4.9498 Max. : 5.417
## NA's :1 NA's :1
## treatment_group
## Length:180
## Class :character
## Mode :character
##
##
##
##
skim(data2)| Name | data2 |
| Number of rows | 180 |
| Number of columns | 108 |
| _______________________ | |
| Column type frequency: | |
| character | 15 |
| numeric | 93 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| ID_sample | 0 | 1.00 | 3 | 5 | 0 | 180 | 0 |
| race_1 | 0 | 1.00 | 5 | 41 | 0 | 6 | 0 |
| ethnicity | 0 | 1.00 | 18 | 22 | 0 | 2 | 0 |
| CKD_cause_1 | 0 | 1.00 | 8 | 57 | 0 | 34 | 0 |
| race_donor_1 | 0 | 1.00 | 5 | 41 | 0 | 6 | 0 |
| ethnicity_donor | 0 | 1.00 | 7 | 22 | 0 | 4 | 0 |
| donor_cause_broad | 0 | 1.00 | 3 | 50 | 0 | 36 | 0 |
| donor_cause_narrow | 0 | 1.00 | 5 | 24 | 0 | 9 | 0 |
| maintenance_1 | 0 | 1.00 | 18 | 173 | 0 | 22 | 0 |
| CMV_mismatch_orig | 0 | 1.00 | 5 | 7 | 0 | 5 | 0 |
| blood_group_rec | 0 | 1.00 | 1 | 2 | 0 | 4 | 0 |
| blood_group_donor | 0 | 1.00 | 1 | 2 | 0 | 4 | 0 |
| DRH | 0 | 1.00 | 8 | 12 | 0 | 3 | 0 |
| death_cause | 174 | 0.03 | 8 | 192 | 0 | 6 | 0 |
| treatment_group | 0 | 1.00 | 7 | 9 | 0 | 2 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| ID_subject | 0 | 1.00 | 17826.56 | 17534.06 | 1001.00 | 5016.75 | 8057.00 | 23007.25 | 57019.00 | ▇▂▁▁▂ |
| TNFR1_stain | 156 | 0.13 | 1.67 | 0.56 | 0.00 | 1.00 | 2.00 | 2.00 | 2.00 | ▁▁▃▁▇ |
| TNFR2_stain | 156 | 0.13 | 0.17 | 0.48 | 0.00 | 0.00 | 0.00 | 0.00 | 2.00 | ▇▁▁▁▁ |
| available | 0 | 1.00 | 1.00 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▁▁▇▁▁ |
| flow | 137 | 0.24 | 1.00 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▁▁▇▁▁ |
| GPL | 0 | 1.00 | 1.91 | 3.31 | 0.13 | 0.63 | 0.94 | 1.74 | 30.76 | ▇▁▁▁▁ |
| MPL | 0 | 1.00 | 6.74 | 7.48 | 0.75 | 2.35 | 4.13 | 7.41 | 41.37 | ▇▁▁▁▁ |
| GPL_BC | 0 | 1.00 | 1.91 | 3.34 | 0.07 | 0.60 | 0.93 | 1.79 | 30.91 | ▇▁▁▁▁ |
| MPL_BC | 0 | 1.00 | 6.64 | 7.69 | 0.02 | 2.14 | 4.08 | 7.77 | 42.72 | ▇▂▁▁▁ |
| GPE_ind | 1 | 0.99 | 0.16 | 0.14 | 0.07 | 0.09 | 0.11 | 0.15 | 0.98 | ▇▁▁▁▁ |
| MPE_ind | 1 | 0.99 | 0.13 | 0.08 | 0.07 | 0.09 | 0.11 | 0.15 | 0.67 | ▇▁▁▁▁ |
| GPE_dep | 1 | 0.99 | 0.23 | 0.15 | 0.08 | 0.16 | 0.19 | 0.25 | 1.33 | ▇▁▁▁▁ |
| MPE_dep | 1 | 0.99 | 0.21 | 0.12 | 0.08 | 0.13 | 0.18 | 0.25 | 1.04 | ▇▂▁▁▁ |
| flow_IgM | 137 | 0.24 | 284641.16 | 143666.42 | 87937.00 | 172979.00 | 241051.00 | 359260.00 | 713000.00 | ▇▃▃▂▁ |
| flow_IgG | 137 | 0.24 | 76880.23 | 24252.75 | 46682.00 | 60076.00 | 74844.00 | 88575.50 | 174621.00 | ▇▇▂▁▁ |
| infliximab | 0 | 1.00 | 0.49 | 0.50 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▇ |
| male_sex | 0 | 1.00 | 0.62 | 0.49 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▅▁▁▁▇ |
| rec_age | 0 | 1.00 | 53.00 | 10.53 | 27.00 | 45.00 | 54.00 | 61.00 | 73.00 | ▂▅▆▇▅ |
| race_2 | 0 | 1.00 | 0.41 | 0.49 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▆ |
| CKD_cause_2 | 0 | 1.00 | 2.56 | 1.23 | 1.00 | 1.75 | 3.00 | 3.00 | 5.00 | ▆▆▇▂▂ |
| RRT_preTx | 0 | 1.00 | 0.92 | 0.28 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▁▁▁▁▇ |
| RRT_months | 15 | 0.92 | 73.55 | 50.47 | 2.00 | 36.00 | 62.00 | 96.00 | 288.00 | ▇▇▂▁▁ |
| RRT_type | 15 | 0.92 | 0.81 | 0.39 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▂▁▁▁▇ |
| dc_graftloss_event_24mo | 0 | 1.00 | 0.03 | 0.18 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| dc_graftloss_time_24mo | 0 | 1.00 | 652.68 | 189.67 | 0.00 | 730.00 | 730.00 | 730.00 | 730.00 | ▁▁▁▁▇ |
| male_sex_donor | 0 | 1.00 | 0.55 | 0.50 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▆▁▁▁▇ |
| age_donor | 1 | 0.99 | 40.30 | 14.25 | 4.00 | 31.50 | 42.00 | 50.00 | 69.00 | ▂▃▇▇▃ |
| race_donor_2 | 0 | 1.00 | 0.62 | 0.49 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▅▁▁▁▇ |
| donor_cause_anoxia | 0 | 1.00 | 0.46 | 0.50 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▇ |
| donor_cause_CVA | 0 | 1.00 | 0.24 | 0.43 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▂ |
| donor_type | 0 | 1.00 | 0.75 | 0.43 | 0.00 | 0.75 | 1.00 | 1.00 | 1.00 | ▂▁▁▁▇ |
| ATG | 0 | 1.00 | 0.99 | 0.07 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▁▁▁▁▇ |
| standard_triple | 0 | 1.00 | 0.89 | 0.32 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▁▁▁▁▇ |
| HLA_MM | 36 | 0.80 | 4.37 | 1.44 | 0.00 | 4.00 | 5.00 | 5.00 | 6.00 | ▁▁▂▃▇ |
| HLAMMGE3 | 0 | 1.00 | 0.85 | 0.36 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▂▁▁▁▇ |
| EBV_IgG | 0 | 1.00 | 1.00 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▁▁▇▁▁ |
| CMV_IgG_rec | 0 | 1.00 | 0.66 | 0.47 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▅▁▁▁▇ |
| CMV_IgG_donor | 1 | 0.99 | 0.58 | 0.50 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▆▁▁▁▇ |
| CMV_mismatch | 1 | 0.99 | 0.19 | 0.39 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▂ |
| KDPI | 0 | 1.00 | 53.73 | 20.62 | 20.00 | 36.75 | 53.00 | 71.25 | 93.00 | ▇▇▆▆▅ |
| WIT | 7 | 0.96 | 37.02 | 21.46 | 0.00 | 27.00 | 33.00 | 42.00 | 209.00 | ▇▂▁▁▁ |
| CIT | 3 | 0.98 | 15.92 | 7.17 | 3.27 | 10.27 | 15.37 | 20.55 | 50.13 | ▆▇▃▁▁ |
| perfusion_event | 21 | 0.88 | 0.40 | 0.49 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▅ |
| perfusion_time | 147 | 0.18 | 11.30 | 4.88 | 2.00 | 8.00 | 11.00 | 15.00 | 19.00 | ▅▃▇▅▇ |
| resistance_index | 132 | 0.27 | 0.21 | 0.11 | 0.00 | 0.15 | 0.21 | 0.25 | 0.70 | ▂▇▂▁▁ |
| TCMR_6mo_event | 66 | 0.63 | 0.04 | 0.21 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| TCMR_6mo_time | 66 | 0.63 | 175.32 | 20.14 | 63.00 | 180.00 | 180.00 | 180.00 | 180.00 | ▁▁▁▁▇ |
| TCMRB_6mo_event | 66 | 0.63 | 0.18 | 0.38 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▂ |
| TCMRB_6mo_time | 66 | 0.63 | 161.62 | 42.27 | 11.00 | 180.00 | 180.00 | 180.00 | 183.00 | ▁▁▁▁▇ |
| TCMR_24mo_event | 57 | 0.68 | 0.09 | 0.29 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| TCMR_24mo_time | 57 | 0.68 | 644.98 | 192.07 | 63.00 | 730.00 | 730.00 | 730.00 | 730.00 | ▁▁▁▁▇ |
| TCMRB_24mo_event | 57 | 0.68 | 0.28 | 0.45 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▃ |
| TCMRB_24mo_time | 57 | 0.68 | 558.97 | 262.62 | 11.00 | 370.50 | 730.00 | 730.00 | 749.00 | ▂▁▁▁▇ |
| AMR_6mo_event | 66 | 0.63 | 0.03 | 0.16 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| AMR_6mo_time | 66 | 0.63 | 175.88 | 21.10 | 41.00 | 180.00 | 180.00 | 180.00 | 180.00 | ▁▁▁▁▇ |
| AMR_24mo_event | 57 | 0.68 | 0.06 | 0.23 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| AMR_24mo_time | 57 | 0.68 | 667.95 | 166.15 | 41.00 | 730.00 | 730.00 | 730.00 | 738.00 | ▁▁▁▁▇ |
| rejection_6mo_central | 69 | 0.62 | 0.03 | 0.16 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| rejectionB_6mo_central | 69 | 0.62 | 0.07 | 0.26 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| rejection_24mo_central | 61 | 0.66 | 0.03 | 0.18 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| rejectionB_24mo_central | 61 | 0.66 | 0.11 | 0.31 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| CKD_EPI_3_vs_24 | 91 | 0.49 | 3.26 | 14.66 | -35.49 | -3.80 | 1.33 | 12.52 | 50.76 | ▁▆▇▃▁ |
| CKD_EPI_6_vs_24 | 94 | 0.48 | 2.92 | 12.16 | -35.81 | -3.25 | 2.80 | 10.97 | 38.16 | ▁▂▇▃▁ |
| DGF | 0 | 1.00 | 0.35 | 0.48 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▅ |
| CRR_day_2 | 66 | 0.63 | 19.87 | 20.13 | -24.20 | 5.69 | 21.65 | 33.29 | 60.87 | ▃▅▇▇▃ |
| CRR_below_30_day_2 | 66 | 0.63 | 0.68 | 0.47 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▃▁▁▁▇ |
| CRR_day_5 | 66 | 0.63 | 42.78 | 28.23 | -43.44 | 30.08 | 47.32 | 63.48 | 84.22 | ▁▂▃▇▇ |
| CRR_below_70_day_5 | 66 | 0.63 | 0.83 | 0.37 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▂▁▁▁▇ |
| preformed_DSA | 2 | 0.99 | 0.03 | 0.17 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| de_novo_DSA | 2 | 0.99 | 0.06 | 0.24 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| infection_any | 0 | 1.00 | 0.43 | 0.50 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▆ |
| infection_wo_BKV | 0 | 1.00 | 0.31 | 0.46 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▃ |
| infection_with_BKV | 0 | 1.00 | 0.52 | 0.50 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▇▁▁▁▇ |
| infection_with_BKV_2 | 0 | 1.00 | 0.52 | 0.50 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▇▁▁▁▇ |
| BKV_event_2 | 0 | 1.00 | 0.22 | 0.41 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▂ |
| BKV_viremia_event | 0 | 1.00 | 0.22 | 0.41 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▂ |
| BKV_viremia_time | 0 | 1.00 | 684.03 | 473.89 | 0.00 | 188.75 | 735.00 | 939.25 | 1854.00 | ▇▅▆▃▁ |
| terminated_event | 0 | 1.00 | 0.19 | 0.39 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▂ |
| terminated_days | 146 | 0.19 | 373.41 | 316.48 | 0.00 | 121.25 | 258.50 | 561.25 | 1323.00 | ▇▂▃▁▁ |
| death_event | 0 | 1.00 | 0.03 | 0.18 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| death_date | 174 | 0.03 | 43428.17 | 153.81 | 43181.00 | 43370.50 | 43425.00 | 43552.25 | 43591.00 | ▃▁▇▃▇ |
| death_time | 174 | 0.03 | 376.33 | 217.96 | 6.00 | 295.00 | 421.00 | 518.50 | 606.00 | ▃▁▃▇▇ |
| death_time_730 | 0 | 1.00 | 656.81 | 186.21 | 0.00 | 730.00 | 730.00 | 730.00 | 730.00 | ▁▁▁▁▇ |
| death_24mo | 0 | 1.00 | 0.03 | 0.18 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| GFR_days | 2 | 0.99 | 542.43 | 248.23 | 26.00 | 369.25 | 692.50 | 740.75 | 919.00 | ▅▃▃▇▇ |
| GFR_MDRD | 2 | 0.99 | 51.91 | 20.20 | 8.44 | 39.08 | 50.00 | 64.56 | 123.48 | ▃▇▆▂▁ |
| GFR_CKD | 2 | 0.99 | 54.26 | 22.33 | 8.88 | 38.17 | 51.65 | 66.01 | 106.01 | ▂▇▇▃▂ |
| GPE_dep_log2 | 1 | 0.99 | -2.28 | 0.66 | -3.64 | -2.68 | -2.39 | -2.00 | 0.42 | ▂▇▂▁▁ |
| MPE_dep_log2 | 1 | 0.99 | -2.40 | 0.67 | -3.61 | -2.93 | -2.46 | -2.00 | 0.06 | ▆▇▆▁▁ |
| GPE_ind_log2 | 1 | 0.99 | -2.93 | 0.73 | -3.87 | -3.41 | -3.16 | -2.71 | -0.03 | ▇▅▁▁▁ |
| MPE_ind_log2 | 1 | 0.99 | -3.03 | 0.57 | -3.90 | -3.45 | -3.15 | -2.70 | -0.57 | ▇▇▃▁▁ |
| GPL_BC_log2 | 0 | 1.00 | 0.11 | 1.41 | -3.86 | -0.73 | -0.10 | 0.84 | 4.95 | ▁▇▇▃▁ |
| MPL_BC_log2 | 0 | 1.00 | 2.00 | 1.55 | -5.53 | 1.10 | 2.03 | 2.96 | 5.42 | ▁▁▃▇▃ |
There are two variables that are expected to affect the outcomes but include many missing values. Look which variables are correlated with these variables (perfusion_event and HLA_MM) so these may be helpful for the imputation.
Open code
safe_cor <- function(x, y) {
if (sd(x, na.rm = TRUE) == 0 || sd(y, na.rm = TRUE) == 0) {
NA_real_
} else {
cor(x, y, use = "pairwise.complete.obs", method = 'pearson')
}
}
df <- data2 %>%
select(where(is.numeric))
res <- tibble(
variable = names(df),
cor_perfusion = map_dbl(variable, ~ safe_cor(df[[.x]], df$perfusion_event)),
cor_hla = map_dbl(variable, ~ safe_cor(df[[.x]], df$HLA_MM)),
n_na = map_int(variable, ~ sum(is.na(df[[.x]])))
) %>%
mutate(max_abs_cor = pmax(abs(cor_perfusion), abs(cor_hla), na.rm = TRUE)) %>%
arrange(desc(max_abs_cor))
## Warning in cor(x, y, use = "pairwise.complete.obs", method = "pearson"): the
## standard deviation is zero
## Warning in cor(x, y, use = "pairwise.complete.obs", method = "pearson"): the
## standard deviation is zero
## Warning in cor(x, y, use = "pairwise.complete.obs", method = "pearson"): the
## standard deviation is zero
kableExtra::kable(res %>% filter(n_na<10, max_abs_cor>0.1))| variable | cor_perfusion | cor_hla | n_na | max_abs_cor |
|---|---|---|---|---|
| HLAMMGE3 | 0.1521796 | 0.7388502 | 0 | 0.7388502 |
| BKV_viremia_time | 0.2740103 | -0.0162880 | 0 | 0.2740103 |
| GFR_CKD | -0.1605158 | -0.2709311 | 2 | 0.2709311 |
| race_2 | 0.2353864 | -0.1944819 | 0 | 0.2353864 |
| GFR_MDRD | -0.1685550 | -0.2334869 | 2 | 0.2334869 |
| GPE_ind | 0.2170082 | 0.0316690 | 1 | 0.2170082 |
| race_donor_2 | 0.2131970 | -0.0264465 | 0 | 0.2131970 |
| age_donor | 0.1486748 | 0.1994518 | 1 | 0.1994518 |
| CIT | 0.1903365 | -0.1393050 | 3 | 0.1903365 |
| CMV_IgG_rec | -0.0818317 | 0.1860303 | 0 | 0.1860303 |
| de_novo_DSA | 0.0807407 | 0.1769103 | 2 | 0.1769103 |
| KDPI | 0.0744357 | 0.1750746 | 0 | 0.1750746 |
| donor_type | -0.1691540 | 0.0328450 | 0 | 0.1691540 |
| GPE_ind_log2 | 0.1687633 | 0.0447728 | 1 | 0.1687633 |
| ID_subject | 0.1620089 | -0.1226652 | 0 | 0.1620089 |
| MPE_dep | -0.1584339 | 0.0166590 | 1 | 0.1584339 |
| MPL_BC | -0.1555197 | -0.0622218 | 0 | 0.1555197 |
| MPL_BC_log2 | -0.1518460 | -0.0367600 | 0 | 0.1518460 |
| GPL_BC_log2 | -0.1480250 | -0.1102327 | 0 | 0.1480250 |
| RRT_preTx | -0.0024901 | -0.1451204 | 0 | 0.1451204 |
| MPE_dep_log2 | -0.1448089 | 0.0124194 | 1 | 0.1448089 |
| GPL_BC | -0.1132365 | -0.1437448 | 0 | 0.1437448 |
| CMV_IgG_donor | 0.0710178 | 0.1437226 | 1 | 0.1437226 |
| GPL | -0.1130782 | -0.1432358 | 0 | 0.1432358 |
| male_sex | 0.1431312 | 0.0824554 | 0 | 0.1431312 |
| MPL | -0.1421092 | -0.0587360 | 0 | 0.1421092 |
| WIT | 0.1409576 | -0.0638921 | 7 | 0.1409576 |
| DGF | -0.0424969 | 0.1340953 | 0 | 0.1340953 |
| male_sex_donor | -0.0485702 | -0.1333746 | 0 | 0.1333746 |
| dc_graftloss_event_24mo | -0.1301364 | -0.0487302 | 0 | 0.1301364 |
| infliximab | 0.0591993 | 0.1247757 | 0 | 0.1247757 |
| MPE_ind | -0.1246244 | -0.0598818 | 1 | 0.1246244 |
| GFR_days | 0.1222818 | 0.0609560 | 2 | 0.1222818 |
| rec_age | -0.0243711 | 0.1218259 | 0 | 0.1218259 |
| preformed_DSA | -0.1142633 | -0.0309393 | 2 | 0.1142633 |
| MPE_ind_log2 | -0.1014825 | -0.0061797 | 1 | 0.1014825 |
3.1 Summary tables
Who will be deleted?
Open code
data2 %>%
filter(is.na(GFR_MDRD) |
is.na(GPE_dep) |
is.na(MPE_dep)
) %>% select(ID_subject)
## ID_subject
## 1 3027
## 2 23007
## 3 570193.1.1 Demography
Open code
data2 %>%
filter(!is.na(GFR_MDRD),
!is.na(GPE_dep),
!is.na(MPE_dep)) %>%
select(male_sex, rec_age, race_2, race_1, ethnicity, treatment_group, CKD_cause_2, RRT_preTx, RRT_months, RRT_type, male_sex_donor, age_donor, race_donor_2, race_donor_1, donor_cause_narrow, donor_cause_anoxia, donor_cause_CVA, donor_type, ATG, standard_triple, HLA_MM, KDPI, WIT, CIT, perfusion_event, perfusion_time, preformed_DSA) %>%
tbl_summary(by = treatment_group, type = list(HLA_MM ~ "continuous")) %>%
add_p() %>%
add_overall()
## The following warnings were returned during `add_p()`:
## ! For variable `perfusion_time` (`treatment_group`) and "estimate",
## "statistic", "p.value", "conf.low", and "conf.high" statistics: cannot
## compute exact p-value with ties
## ! For variable `perfusion_time` (`treatment_group`) and "estimate",
## "statistic", "p.value", "conf.low", and "conf.high" statistics: cannot
## compute exact confidence intervals with tiesCharacteristic |
Overall |
infiximab |
placebo |
p-value 2 |
|---|---|---|---|---|
| male_sex | 109 (62%) | 59 (68%) | 50 (56%) | 0.094 |
| rec_age | 54 (45, 61) | 54 (46, 61) | 55 (45, 62) | >0.9 |
| race_2 | 72 (41%) | 35 (40%) | 37 (41%) | >0.9 |
| race_1 | 0.9 | |||
| American Indian or Alaska Native | 1 (0.6%) | 1 (1.1%) | 0 (0%) | |
| Asian | 9 (5.1%) | 5 (5.7%) | 4 (4.4%) | |
| Black or African American | 73 (41%) | 34 (39%) | 39 (43%) | |
| Native Hawaiian or Other Pacific Islander | 3 (1.7%) | 1 (1.1%) | 2 (2.2%) | |
| Unknown or Not Reported | 19 (11%) | 11 (13%) | 8 (8.9%) | |
| White | 72 (41%) | 35 (40%) | 37 (41%) | |
| ethnicity | 0.2 | |||
| Hispanic or Latino | 25 (14%) | 15 (17%) | 10 (11%) | |
| Not Hispanic or Latino | 152 (86%) | 72 (83%) | 80 (89%) | |
| CKD_cause_2 | 0.3 | |||
| 1 | 44 (25%) | 23 (26%) | 21 (23%) | |
| 2 | 42 (24%) | 22 (25%) | 20 (22%) | |
| 3 | 58 (33%) | 27 (31%) | 31 (34%) | |
| 4 | 18 (10%) | 11 (13%) | 7 (7.8%) | |
| 5 | 15 (8.5%) | 4 (4.6%) | 11 (12%) | |
| RRT_preTx | 162 (92%) | 80 (92%) | 82 (91%) | 0.8 |
| RRT_months | 62 (36, 95) | 63 (37, 92) | 62 (36, 96) | >0.9 |
| Unknown | 15 | 7 | 8 | |
| RRT_type | 132 (81%) | 64 (80%) | 68 (83%) | 0.6 |
| Unknown | 15 | 7 | 8 | |
| male_sex_donor | 98 (55%) | 43 (49%) | 55 (61%) | 0.12 |
| age_donor | 43 (32, 50) | 44 (32, 50) | 42 (30, 50) | 0.5 |
| Unknown | 1 | 1 | 0 | |
| race_donor_2 | 109 (62%) | 59 (68%) | 50 (56%) | 0.094 |
| race_donor_1 | 0.033 | |||
| American Indian or Alaska Native | 2 (1.1%) | 0 (0%) | 2 (2.2%) | |
| Asian | 9 (5.1%) | 2 (2.3%) | 7 (7.8%) | |
| Black or African American | 30 (17%) | 10 (11%) | 20 (22%) | |
| Native Hawaiian or Other Pacific Islander | 1 (0.6%) | 0 (0%) | 1 (1.1%) | |
| Unknown or Not Reported | 26 (15%) | 16 (18%) | 10 (11%) | |
| White | 109 (62%) | 59 (68%) | 50 (56%) | |
| donor_cause_narrow | >0.9 | |||
| Anoxia | 82 (46%) | 38 (44%) | 44 (49%) | |
| Cardiovascular | 5 (2.8%) | 2 (2.3%) | 3 (3.3%) | |
| Cerebrovascular Accident | 42 (24%) | 22 (25%) | 20 (22%) | |
| CNS-Other | 1 (0.6%) | 0 (0%) | 1 (1.1%) | |
| Drug Overdose | 2 (1.1%) | 1 (1.1%) | 1 (1.1%) | |
| Head Trauma | 38 (21%) | 21 (24%) | 17 (19%) | |
| Infection | 2 (1.1%) | 1 (1.1%) | 1 (1.1%) | |
| Other | 2 (1.1%) | 1 (1.1%) | 1 (1.1%) | |
| Respiratory Failure | 3 (1.7%) | 1 (1.1%) | 2 (2.2%) | |
| donor_cause_anoxia | 82 (46%) | 38 (44%) | 44 (49%) | 0.5 |
| donor_cause_CVA | 42 (24%) | 22 (25%) | 20 (22%) | 0.6 |
| donor_type | 133 (75%) | 64 (74%) | 69 (77%) | 0.6 |
| ATG | 176 (99%) | 87 (100%) | 89 (99%) | >0.9 |
| standard_triple | 158 (89%) | 76 (87%) | 82 (91%) | 0.4 |
| HLA_MM | 5.00 (4.00, 5.00) | 5.00 (4.00, 6.00) | 4.00 (3.50, 5.00) | 0.080 |
| Unknown | 35 | 17 | 18 | |
| KDPI | 53 (37, 71) | 53 (32, 71) | 51 (39, 74) | 0.4 |
| WIT | 33 (27, 42) | 33 (27, 42) | 33 (27, 40) | 0.9 |
| Unknown | 6 | 3 | 3 | |
| CIT | 15 (10, 21) | 16 (10, 21) | 15 (10, 20) | 0.8 |
| Unknown | 3 | 3 | 0 | |
| perfusion_event | 63 (40%) | 34 (44%) | 29 (37%) | 0.4 |
| Unknown | 21 | 9 | 12 | |
| perfusion_time | 11.0 (8.0, 15.0) | 12.0 (8.0, 15.0) | 11.0 (6.0, 16.0) | 0.5 |
| Unknown | 144 | 68 | 76 | |
| preformed_DSA | 5 (2.8%) | 2 (2.3%) | 3 (3.3%) | >0.9 |
| 1
n (%); Median (Q1, Q3) |
||||
| 2
Pearson’s Chi-squared test; Wilcoxon rank sum test; Fisher’s exact test |
||||
3.1.2 Demography stratified treatment and aCL IgG groups
Open code
sum_data <- data2 %>%
filter(!is.na(GFR_MDRD),
!is.na(GPE_dep),
!is.na(MPE_dep)) %>%
dplyr::select(
DGF, infection_any, GFR_MDRD, BKV_event_2,
GPL_BC,
MPL_BC,
GPE_dep,
GPE_ind,
MPE_dep,
MPE_ind,
male_sex,
HLA_MM,
male_sex_donor,
KDPI,
perfusion_event,
CIT,
infliximab,
rec_age,
race_2, race_1, ethnicity, CKD_cause_2, RRT_preTx, RRT_months, RRT_type, age_donor,
race_donor_2, race_donor_1, donor_cause_narrow, donor_cause_anoxia, donor_cause_CVA,
donor_type, ATG, standard_triple, WIT, perfusion_event, perfusion_time, preformed_DSA) %>%
mutate(aCL_IgG_category = if_else(GPL_BC < median(data2$GPL_BC, na.rm =TRUE),
'low aCL IgG', 'high aCL'
),
treatment = if_else(infliximab == 1, 'IFX', 'PCO')
) %>%
mutate(category = interaction(treatment, aCL_IgG_category))
sum_data %>% select(-c(infliximab, aCL_IgG_category, GPL_BC:MPE_ind)) %>%
gtsummary::tbl_summary(by = category,
type = list(HLA_MM ~ "continuous")) %>%
add_p() %>%
add_overall()
## The following errors were returned during `add_p()`:
## ✖ For variable `CKD_cause_2` (`category`) and "estimate", "p.value",
## "conf.low", and "conf.high" statistics: FEXACT error 7(location). LDSTP=18630
## is too small for this problem, (pastp=85.2787, ipn_0:=ipoin[itp=620]=102,
## stp[ipn_0]=84.8266). Increase workspace or consider using
## 'simulate.p.value=TRUE'
## ✖ For variable `donor_cause_narrow` (`category`) and "estimate", "p.value",
## "conf.low", and "conf.high" statistics: FEXACT error 6. LDKEY=621 is too
## small for this problem, (ii := key2[itp=484] = 3638300, ldstp=18630) Try
## increasing the size of the workspace and possibly 'mult'
## ✖ For variable `race_donor_1` (`category`) and "estimate", "p.value",
## "conf.low", and "conf.high" statistics: FEXACT error 7(location). LDSTP=18630
## is too small for this problem, (pastp=37.0568, ipn_0:=ipoin[itp=277]=2971,
## stp[ipn_0]=36.487). Increase workspace or consider using
## 'simulate.p.value=TRUE'Characteristic |
Overall |
IFX.high aCL |
PCO.high aCL |
IFX.low aCL IgG |
PCO.low aCL IgG |
p-value 2 |
|---|---|---|---|---|---|---|
| DGF | 60 (34%) | 19 (46%) | 14 (30%) | 9 (20%) | 18 (42%) | 0.035 |
| infection_any | 75 (42%) | 17 (41%) | 17 (36%) | 21 (46%) | 20 (47%) | 0.7 |
| GFR_MDRD | 50 (39, 65) | 45 (35, 51) | 58 (44, 70) | 56 (40, 68) | 47 (35, 62) | 0.029 |
| BKV_event_2 | 38 (21%) | 12 (29%) | 5 (11%) | 13 (28%) | 8 (19%) | 0.10 |
| male_sex | 109 (62%) | 26 (63%) | 26 (55%) | 33 (72%) | 24 (56%) | 0.3 |
| HLA_MM | 5.00 (4.00, 5.00) | 5.00 (4.00, 5.00) | 4.50 (4.00, 5.00) | 5.00 (4.00, 6.00) | 4.00 (3.00, 5.50) | 0.15 |
| Unknown | 35 | 8 | 11 | 9 | 7 | |
| male_sex_donor | 98 (55%) | 19 (46%) | 29 (62%) | 24 (52%) | 26 (60%) | 0.4 |
| KDPI | 53 (37, 71) | 49 (29, 66) | 52 (37, 76) | 54 (35, 72) | 50 (39, 74) | 0.6 |
| perfusion_event | 63 (40%) | 15 (41%) | 14 (32%) | 19 (46%) | 15 (44%) | 0.5 |
| Unknown | 21 | 4 | 3 | 5 | 9 | |
| CIT | 15 (10, 21) | 17 (10, 21) | 16 (10, 22) | 14 (10, 20) | 14 (10, 20) | 0.7 |
| Unknown | 3 | 1 | 0 | 2 | 0 | |
| rec_age | 54 (45, 61) | 53 (45, 60) | 55 (45, 61) | 56 (48, 63) | 54 (45, 63) | 0.8 |
| race_2 | 72 (41%) | 16 (39%) | 17 (36%) | 19 (41%) | 20 (47%) | 0.8 |
| race_1 | 0.8 | |||||
| American Indian or Alaska Native | 1 (0.6%) | 0 (0%) | 0 (0%) | 1 (2.2%) | 0 (0%) | |
| Asian | 9 (5.1%) | 1 (2.4%) | 3 (6.4%) | 4 (8.7%) | 1 (2.3%) | |
| Black or African American | 73 (41%) | 18 (44%) | 22 (47%) | 16 (35%) | 17 (40%) | |
| Native Hawaiian or Other Pacific Islander | 3 (1.7%) | 1 (2.4%) | 0 (0%) | 0 (0%) | 2 (4.7%) | |
| Unknown or Not Reported | 19 (11%) | 5 (12%) | 5 (11%) | 6 (13%) | 3 (7.0%) | |
| White | 72 (41%) | 16 (39%) | 17 (36%) | 19 (41%) | 20 (47%) | |
| ethnicity | 0.4 | |||||
| Hispanic or Latino | 25 (14%) | 8 (20%) | 7 (15%) | 7 (15%) | 3 (7.0%) | |
| Not Hispanic or Latino | 152 (86%) | 33 (80%) | 40 (85%) | 39 (85%) | 40 (93%) | |
| CKD_cause_2 | ||||||
| 1 | 44 (25%) | 10 (24%) | 11 (23%) | 13 (28%) | 10 (23%) | |
| 2 | 42 (24%) | 9 (22%) | 9 (19%) | 13 (28%) | 11 (26%) | |
| 3 | 58 (33%) | 13 (32%) | 15 (32%) | 14 (30%) | 16 (37%) | |
| 4 | 18 (10%) | 5 (12%) | 5 (11%) | 6 (13%) | 2 (4.7%) | |
| 5 | 15 (8.5%) | 4 (9.8%) | 7 (15%) | 0 (0%) | 4 (9.3%) | |
| RRT_preTx | 162 (92%) | 41 (100%) | 39 (83%) | 39 (85%) | 43 (100%) | <0.001 |
| RRT_months | 62 (36, 95) | 73 (49, 105) | 60 (39, 83) | 51 (36, 81) | 65 (34, 115) | 0.3 |
| Unknown | 15 | 0 | 8 | 7 | 0 | |
| RRT_type | 132 (81%) | 37 (90%) | 33 (85%) | 27 (69%) | 35 (81%) | 0.10 |
| Unknown | 15 | 0 | 8 | 7 | 0 | |
| age_donor | 43 (32, 50) | 38 (32, 48) | 43 (24, 50) | 45 (34, 50) | 41 (32, 52) | 0.7 |
| Unknown | 1 | 0 | 0 | 1 | 0 | |
| race_donor_2 | 109 (62%) | 28 (68%) | 27 (57%) | 31 (67%) | 23 (53%) | 0.4 |
| race_donor_1 | ||||||
| American Indian or Alaska Native | 2 (1.1%) | 0 (0%) | 1 (2.1%) | 0 (0%) | 1 (2.3%) | |
| Asian | 9 (5.1%) | 1 (2.4%) | 3 (6.4%) | 1 (2.2%) | 4 (9.3%) | |
| Black or African American | 30 (17%) | 3 (7.3%) | 9 (19%) | 7 (15%) | 11 (26%) | |
| Native Hawaiian or Other Pacific Islander | 1 (0.6%) | 0 (0%) | 0 (0%) | 0 (0%) | 1 (2.3%) | |
| Unknown or Not Reported | 26 (15%) | 9 (22%) | 7 (15%) | 7 (15%) | 3 (7.0%) | |
| White | 109 (62%) | 28 (68%) | 27 (57%) | 31 (67%) | 23 (53%) | |
| donor_cause_narrow | ||||||
| Anoxia | 82 (46%) | 18 (44%) | 24 (51%) | 20 (43%) | 20 (47%) | |
| Cardiovascular | 5 (2.8%) | 1 (2.4%) | 2 (4.3%) | 1 (2.2%) | 1 (2.3%) | |
| Cerebrovascular Accident | 42 (24%) | 7 (17%) | 10 (21%) | 15 (33%) | 10 (23%) | |
| CNS-Other | 1 (0.6%) | 0 (0%) | 0 (0%) | 0 (0%) | 1 (2.3%) | |
| Drug Overdose | 2 (1.1%) | 0 (0%) | 0 (0%) | 1 (2.2%) | 1 (2.3%) | |
| Head Trauma | 38 (21%) | 14 (34%) | 8 (17%) | 7 (15%) | 9 (21%) | |
| Infection | 2 (1.1%) | 1 (2.4%) | 1 (2.1%) | 0 (0%) | 0 (0%) | |
| Other | 2 (1.1%) | 0 (0%) | 1 (2.1%) | 1 (2.2%) | 0 (0%) | |
| Respiratory Failure | 3 (1.7%) | 0 (0%) | 1 (2.1%) | 1 (2.2%) | 1 (2.3%) | |
| donor_cause_anoxia | 82 (46%) | 18 (44%) | 24 (51%) | 20 (43%) | 20 (47%) | 0.9 |
| donor_cause_CVA | 42 (24%) | 7 (17%) | 10 (21%) | 15 (33%) | 10 (23%) | 0.4 |
| donor_type | 133 (75%) | 27 (66%) | 35 (74%) | 37 (80%) | 34 (79%) | 0.4 |
| ATG | 176 (99%) | 41 (100%) | 47 (100%) | 46 (100%) | 42 (98%) | 0.5 |
| standard_triple | 158 (89%) | 34 (83%) | 43 (91%) | 42 (91%) | 39 (91%) | 0.6 |
| WIT | 33 (27, 42) | 32 (25, 42) | 32 (26, 38) | 35 (28, 43) | 37 (29, 47) | 0.2 |
| Unknown | 6 | 1 | 1 | 2 | 2 | |
| perfusion_time | 11.0 (8.0, 15.0) | 14.0 (12.0, 16.0) | 16.0 (11.0, 16.0) | 11.0 (5.0, 14.0) | 8.0 (5.0, 11.0) | 0.030 |
| Unknown | 144 | 32 | 40 | 36 | 36 | |
| preformed_DSA | 5 (2.8%) | 2 (4.9%) | 2 (4.3%) | 0 (0%) | 1 (2.3%) | 0.5 |
| treatment | <0.001 | |||||
| IFX | 87 (49%) | 41 (100%) | 0 (0%) | 46 (100%) | 0 (0%) | |
| PCO | 90 (51%) | 0 (0%) | 47 (100%) | 0 (0%) | 43 (100%) | |
| 1
n (%); Median (Q1, Q3) |
||||||
| 2
Pearson’s Chi-squared test; Kruskal-Wallis rank sum test; Fisher’s exact test |
||||||
3.1.3 Outcomes by treatment arm
Open code
sum_data %>% select(treatment, DGF:BKV_event_2) %>%
gtsummary::tbl_summary(by = treatment) %>%
add_p() %>%
add_overall()Characteristic |
Overall |
IFX |
PCO |
p-value 2 |
|---|---|---|---|---|
| DGF | 60 (34%) | 28 (32%) | 32 (36%) | 0.6 |
| infection_any | 75 (42%) | 38 (44%) | 37 (41%) | 0.7 |
| GFR_MDRD | 50 (39, 65) | 50 (39, 62) | 51 (39, 66) | 0.3 |
| BKV_event_2 | 38 (21%) | 25 (29%) | 13 (14%) | 0.021 |
| 1
n (%); Median (Q1, Q3) |
||||
| 2
Pearson’s Chi-squared test; Wilcoxon rank sum test |
||||
3.1.4 Antigens
3.1.4.1 In general
Open code
data2 %>%
filter(
!is.na(GFR_MDRD),
!is.na(GPE_dep_log2),
!is.na(MPE_dep_log2)
) %>%
select(
treatment_group,
GPL_BC, MPL_BC, MPE_ind, MPE_dep, GPE_ind, GPE_dep
) %>%
tbl_summary(by = treatment_group) %>%
add_p() %>%
add_overall()Characteristic |
Overall |
infiximab |
placebo |
p-value 2 |
|---|---|---|---|---|
| GPL_BC | 0.93 (0.60, 1.80) | 0.87 (0.56, 1.55) | 0.96 (0.65, 2.08) | 0.3 |
| MPL_BC | 4 (2, 8) | 3 (2, 6) | 5 (2, 10) | 0.005 |
| MPE_ind | 0.11 (0.09, 0.15) | 0.11 (0.09, 0.15) | 0.12 (0.09, 0.15) | 0.6 |
| MPE_dep | 0.18 (0.13, 0.25) | 0.18 (0.12, 0.25) | 0.19 (0.14, 0.26) | 0.4 |
| GPE_ind | 0.11 (0.09, 0.15) | 0.12 (0.10, 0.15) | 0.11 (0.09, 0.15) | 0.7 |
| GPE_dep | 0.19 (0.16, 0.25) | 0.19 (0.15, 0.26) | 0.19 (0.16, 0.24) | 0.3 |
| 1
Median (Q1, Q3) |
||||
| 2
Wilcoxon rank sum test |
||||
3.1.4.2 Only these with DGF
Open code
data2 %>%
filter(!is.na(GFR_MDRD),
!is.na(GPE_dep_log2),
!is.na(MPE_dep_log2)) %>%
filter(DGF == 1) %>%
select(treatment_group,
GPL_BC, MPL_BC, MPE_ind, MPE_dep, GPE_ind, GPE_dep) %>%
tbl_summary(by = treatment_group) %>%
add_p() %>%
add_overall()
## The following warnings were returned during `add_p()`:
## ! For variable `GPE_dep` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## p-value with ties
## ! For variable `GPE_dep` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## confidence intervals with ties
## ! For variable `GPE_ind` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## p-value with ties
## ! For variable `GPE_ind` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## confidence intervals with ties
## ! For variable `MPE_dep` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## p-value with ties
## ! For variable `MPE_dep` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## confidence intervals with ties
## ! For variable `MPE_ind` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## p-value with ties
## ! For variable `MPE_ind` (`treatment_group`) and "estimate", "statistic",
## "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
## confidence intervals with tiesCharacteristic |
Overall |
infiximab |
placebo |
p-value 2 |
|---|---|---|---|---|
| GPL_BC | 0.96 (0.59, 2.55) | 1.15 (0.75, 3.32) | 0.80 (0.57, 1.87) | 0.2 |
| MPL_BC | 6 (3, 9) | 6 (3, 8) | 6 (3, 12) | 0.8 |
| MPE_ind | 0.11 (0.09, 0.15) | 0.11 (0.09, 0.17) | 0.11 (0.09, 0.14) | >0.9 |
| MPE_dep | 0.17 (0.13, 0.25) | 0.22 (0.14, 0.26) | 0.16 (0.12, 0.25) | 0.4 |
| GPE_ind | 0.12 (0.09, 0.15) | 0.13 (0.10, 0.15) | 0.11 (0.09, 0.15) | 0.3 |
| GPE_dep | 0.20 (0.15, 0.28) | 0.20 (0.16, 0.27) | 0.18 (0.13, 0.30) | 0.5 |
| 1
Median (Q1, Q3) |
||||
| 2
Wilcoxon rank sum exact test; Wilcoxon rank sum test |
||||
3.1.4.3 Only these without DGF
Open code
data2 %>%
filter(!is.na(GFR_MDRD),
!is.na(GPE_dep_log2),
!is.na(MPE_dep_log2)) %>%
filter(DGF == 0) %>%
select(treatment_group,
GPL_BC, MPL_BC, MPE_ind, MPE_dep, GPE_ind, GPE_dep) %>%
tbl_summary(by = treatment_group) %>%
add_p() %>%
add_overall()Characteristic |
Overall |
infiximab |
placebo |
p-value 2 |
|---|---|---|---|---|
| GPL_BC | 0.89 (0.61, 1.66) | 0.79 (0.53, 1.28) | 1.09 (0.70, 2.09) | 0.018 |
| MPL_BC | 3.5 (2.0, 6.6) | 2.6 (1.8, 4.7) | 4.6 (2.5, 9.1) | <0.001 |
| MPE_ind | 0.11 (0.09, 0.15) | 0.11 (0.09, 0.15) | 0.12 (0.09, 0.16) | 0.5 |
| MPE_dep | 0.19 (0.13, 0.25) | 0.17 (0.12, 0.23) | 0.20 (0.15, 0.26) | 0.072 |
| GPE_ind | 0.11 (0.09, 0.15) | 0.11 (0.09, 0.15) | 0.11 (0.10, 0.17) | 0.8 |
| GPE_dep | 0.19 (0.16, 0.25) | 0.19 (0.15, 0.26) | 0.19 (0.16, 0.22) | 0.6 |
| 1
Median (Q1, Q3) |
||||
| 2
Wilcoxon rank sum test |
||||
3.2 Antigens data distributions
Open code
data_hist <- data2 %>%
filter(!is.na(GFR_MDRD),
!is.na(GPE_dep_log2),
!is.na(MPE_dep_log2)) %>%
mutate(infliximab = if_else(infliximab == 1, 'IFX', 'PCO'))
p1 <- data_hist %>%
ggplot(aes(x = GPL_BC)) +
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p2 <- data_hist %>%
ggplot(aes(x = GPL_BC_log2))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p3 <- data_hist %>%
ggplot(aes(x = MPL_BC))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p4 <- data_hist %>%
ggplot(aes(x = MPL_BC_log2))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p5 <- data_hist %>%
ggplot(aes(x = MPE_ind))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p6 <- data_hist %>%
ggplot(aes(x = MPE_ind_log2))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p7 <- data_hist %>%
ggplot(aes(x = MPE_dep))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p8 <- data_hist %>%
ggplot(aes(x = MPE_dep_log2))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p9 <- data_hist %>%
ggplot(aes(x = GPE_ind))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p10 <- data_hist %>%
ggplot(aes(x = GPE_ind_log2))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p11 <- data_hist %>%
ggplot(aes(x = GPE_dep))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
p12 <- data_hist %>%
ggplot(aes(x = GPE_dep_log2))+
geom_histogram() +
facet_wrap(~ infliximab, nrow = 2)
plot_grid(p1,p2,p3,p4, p5, p6, p7, p8, p9, p10, p11, p12, nrow = 3)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.4 Data - models-relevant
4.1 Define the model-relevant data
Open code
data_model_priorImpute <- data2 %>%
dplyr::select(
# outcomes
DGF, infection_any, GFR_MDRD, BKV_event_2,
# antigens
GPL_BC_log2,
MPL_BC_log2,
GPE_dep_log2,
GPE_ind_log2,
MPE_dep_log2,
MPE_ind_log2,
# other covariates
male_sex,
HLA_MM,
male_sex_donor,
KDPI,
perfusion_event,
CIT,
infliximab,
rec_age,
# variables for imputation only
HLAMMGE3,
BKV_viremia_time,
race_2,
race_donor_2,
age_donor,
CMV_IgG_rec,
de_novo_DSA,
donor_type
) %>%
filter(!is.na(GFR_MDRD),
!is.na(GPE_dep_log2),
!is.na(MPE_dep_log2))
data_model_priorImpute %>% summary()
## DGF infection_any GFR_MDRD BKV_event_2
## Min. :0.000 Min. :0.0000 Min. : 8.44 Min. :0.0000
## 1st Qu.:0.000 1st Qu.:0.0000 1st Qu.: 39.07 1st Qu.:0.0000
## Median :0.000 Median :0.0000 Median : 49.88 Median :0.0000
## Mean :0.339 Mean :0.4237 Mean : 51.90 Mean :0.2147
## 3rd Qu.:1.000 3rd Qu.:1.0000 3rd Qu.: 64.98 3rd Qu.:0.0000
## Max. :1.000 Max. :1.0000 Max. :123.48 Max. :1.0000
##
## GPL_BC_log2 MPL_BC_log2 GPE_dep_log2 GPE_ind_log2
## Min. :-3.8616 Min. :-5.533 Min. :-3.6439 Min. :-3.86775
## 1st Qu.:-0.7449 1st Qu.: 1.093 1st Qu.:-2.6666 1st Qu.:-3.41120
## Median :-0.1046 Median : 2.043 Median :-2.3921 Median :-3.16488
## Mean : 0.1147 Mean : 1.996 Mean :-2.2821 Mean :-2.92303
## 3rd Qu.: 0.8505 3rd Qu.: 2.942 3rd Qu.:-2.0058 3rd Qu.:-2.70840
## Max. : 4.9498 Max. : 5.417 Max. : 0.4163 Max. :-0.03283
##
## MPE_dep_log2 MPE_ind_log2 male_sex HLA_MM
## Min. :-3.60823 Min. :-3.8997 Min. :0.0000 Min. :0.000
## 1st Qu.:-2.92686 1st Qu.:-3.4501 1st Qu.:0.0000 1st Qu.:4.000
## Median :-2.45799 Median :-3.1520 Median :1.0000 Median :5.000
## Mean :-2.40099 Mean :-3.0307 Mean :0.6158 Mean :4.373
## 3rd Qu.:-1.99712 3rd Qu.:-2.7037 3rd Qu.:1.0000 3rd Qu.:5.000
## Max. : 0.05866 Max. :-0.5724 Max. :1.0000 Max. :6.000
## NA's :35
## male_sex_donor KDPI perfusion_event CIT
## Min. :0.0000 Min. :20.00 Min. :0.0000 Min. : 3.267
## 1st Qu.:0.0000 1st Qu.:37.00 1st Qu.:0.0000 1st Qu.:10.267
## Median :1.0000 Median :53.00 Median :0.0000 Median :15.325
## Mean :0.5537 Mean :53.77 Mean :0.4038 Mean :15.920
## 3rd Qu.:1.0000 3rd Qu.:71.00 3rd Qu.:1.0000 3rd Qu.:20.508
## Max. :1.0000 Max. :93.00 Max. :1.0000 Max. :50.133
## NA's :21 NA's :3
## infliximab rec_age HLAMMGE3 BKV_viremia_time
## Min. :0.0000 Min. :27.00 Min. :0.0000 Min. : 22.0
## 1st Qu.:0.0000 1st Qu.:45.00 1st Qu.:1.0000 1st Qu.: 196.0
## Median :0.0000 Median :54.00 Median :1.0000 Median : 735.0
## Mean :0.4915 Mean :53.15 Mean :0.8475 Mean : 693.9
## 3rd Qu.:1.0000 3rd Qu.:61.00 3rd Qu.:1.0000 3rd Qu.: 952.0
## Max. :1.0000 Max. :73.00 Max. :1.0000 Max. :1854.0
##
## race_2 race_donor_2 age_donor CMV_IgG_rec
## Min. :0.0000 Min. :0.0000 Min. : 4.00 Min. :0.000
## 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:31.75 1st Qu.:0.000
## Median :0.0000 Median :1.0000 Median :42.50 Median :1.000
## Mean :0.4068 Mean :0.6158 Mean :40.33 Mean :0.661
## 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:50.00 3rd Qu.:1.000
## Max. :1.0000 Max. :1.0000 Max. :69.00 Max. :1.000
## NA's :1
## de_novo_DSA donor_type
## Min. :0.00000 Min. :0.0000
## 1st Qu.:0.00000 1st Qu.:1.0000
## Median :0.00000 Median :1.0000
## Mean :0.06215 Mean :0.7514
## 3rd Qu.:0.00000 3rd Qu.:1.0000
## Max. :1.00000 Max. :1.0000
##
## Get mean values
mmale_sex <- mean(data_model_priorImpute$male_sex, na.rm = TRUE)
mmale_sex_donor <- mean(data_model_priorImpute$male_sex_donor, na.rm = TRUE)
mperfusion_event <- mean(data_model_priorImpute$perfusion_event, na.rm = TRUE)
mrec_age <- mean(data_model_priorImpute$rec_age, na.rm = TRUE)
mKDPI <- mean(data_model_priorImpute$KDPI, na.rm = TRUE)
mCIT <- mean(data_model_priorImpute$CIT, na.rm = TRUE)
mHLA_MM <- mean(data_model_priorImpute$HLA_MM, na.rm = TRUE)
mDGF <- mean(data_model_priorImpute$DGF, na.rm = TRUE)4.2 Explore data
Open code
skim(data_model_priorImpute)| Name | data_model_priorImpute |
| Number of rows | 177 |
| Number of columns | 26 |
| _______________________ | |
| Column type frequency: | |
| numeric | 26 |
| ________________________ | |
| Group variables | None |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| DGF | 0 | 1.00 | 0.34 | 0.47 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▅ |
| infection_any | 0 | 1.00 | 0.42 | 0.50 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▆ |
| GFR_MDRD | 0 | 1.00 | 51.90 | 20.26 | 8.44 | 39.07 | 49.88 | 64.98 | 123.48 | ▃▇▆▂▁ |
| BKV_event_2 | 0 | 1.00 | 0.21 | 0.41 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▂ |
| GPL_BC_log2 | 0 | 1.00 | 0.11 | 1.42 | -3.86 | -0.74 | -0.10 | 0.85 | 4.95 | ▁▇▇▃▁ |
| MPL_BC_log2 | 0 | 1.00 | 2.00 | 1.56 | -5.53 | 1.09 | 2.04 | 2.94 | 5.42 | ▁▁▃▇▃ |
| GPE_dep_log2 | 0 | 1.00 | -2.28 | 0.65 | -3.64 | -2.67 | -2.39 | -2.01 | 0.42 | ▂▇▂▁▁ |
| GPE_ind_log2 | 0 | 1.00 | -2.92 | 0.73 | -3.87 | -3.41 | -3.16 | -2.71 | -0.03 | ▇▅▁▁▁ |
| MPE_dep_log2 | 0 | 1.00 | -2.40 | 0.67 | -3.61 | -2.93 | -2.46 | -2.00 | 0.06 | ▆▇▆▁▁ |
| MPE_ind_log2 | 0 | 1.00 | -3.03 | 0.57 | -3.90 | -3.45 | -3.15 | -2.70 | -0.57 | ▇▇▃▁▁ |
| male_sex | 0 | 1.00 | 0.62 | 0.49 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▅▁▁▁▇ |
| HLA_MM | 35 | 0.80 | 4.37 | 1.45 | 0.00 | 4.00 | 5.00 | 5.00 | 6.00 | ▁▁▂▃▇ |
| male_sex_donor | 0 | 1.00 | 0.55 | 0.50 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▆▁▁▁▇ |
| KDPI | 0 | 1.00 | 53.77 | 20.60 | 20.00 | 37.00 | 53.00 | 71.00 | 93.00 | ▇▇▆▆▅ |
| perfusion_event | 21 | 0.88 | 0.40 | 0.49 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▆ |
| CIT | 3 | 0.98 | 15.92 | 7.14 | 3.27 | 10.27 | 15.32 | 20.51 | 50.13 | ▆▇▃▁▁ |
| infliximab | 0 | 1.00 | 0.49 | 0.50 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▇ |
| rec_age | 0 | 1.00 | 53.15 | 10.49 | 27.00 | 45.00 | 54.00 | 61.00 | 73.00 | ▂▅▆▇▅ |
| HLAMMGE3 | 0 | 1.00 | 0.85 | 0.36 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▂▁▁▁▇ |
| BKV_viremia_time | 0 | 1.00 | 693.92 | 471.35 | 22.00 | 196.00 | 735.00 | 952.00 | 1854.00 | ▇▇▅▃▁ |
| race_2 | 0 | 1.00 | 0.41 | 0.49 | 0.00 | 0.00 | 0.00 | 1.00 | 1.00 | ▇▁▁▁▆ |
| race_donor_2 | 0 | 1.00 | 0.62 | 0.49 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▅▁▁▁▇ |
| age_donor | 1 | 0.99 | 40.33 | 14.23 | 4.00 | 31.75 | 42.50 | 50.00 | 69.00 | ▂▃▇▇▃ |
| CMV_IgG_rec | 0 | 1.00 | 0.66 | 0.47 | 0.00 | 0.00 | 1.00 | 1.00 | 1.00 | ▅▁▁▁▇ |
| de_novo_DSA | 0 | 1.00 | 0.06 | 0.24 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | ▇▁▁▁▁ |
| donor_type | 0 | 1.00 | 0.75 | 0.43 | 0.00 | 1.00 | 1.00 | 1.00 | 1.00 | ▂▁▁▁▇ |
4.3 Variables correlations
Is the missingness correlated with outcomes?
Open code
df2_corr <- data_model_priorImpute %>% mutate(
NA_perfusion_event = if_else(is.na(perfusion_event), 1, 0),
NA_HLA_MM = if_else(is.na(HLA_MM), 1, 0)
)
m1 <- glm(NA_perfusion_event ~ DGF, family = 'binomial', data = df2_corr)
summary(m1)
##
## Call:
## glm(formula = NA_perfusion_event ~ DGF, family = "binomial",
## data = df2_corr)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.9169 0.2765 -6.932 0.00000000000415 ***
## DGF -0.2803 0.5115 -0.548 0.584
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 128.93 on 176 degrees of freedom
## Residual deviance: 128.62 on 175 degrees of freedom
## AIC: 132.62
##
## Number of Fisher Scoring iterations: 4
m2 <- glm(NA_perfusion_event ~ infection_any, family = 'binomial', data = df2_corr)
summary(m2)
##
## Call:
## glm(formula = NA_perfusion_event ~ infection_any, family = "binomial",
## data = df2_corr)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.01490 0.30731 -6.556 0.0000000000551 ***
## infection_any 0.02247 0.46979 0.048 0.962
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 128.93 on 176 degrees of freedom
## Residual deviance: 128.93 on 175 degrees of freedom
## AIC: 132.93
##
## Number of Fisher Scoring iterations: 4
m3 <- glm(NA_perfusion_event ~ BKV_event_2, family = 'binomial', data = df2_corr)
summary(m2)
##
## Call:
## glm(formula = NA_perfusion_event ~ infection_any, family = "binomial",
## data = df2_corr)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.01490 0.30731 -6.556 0.0000000000551 ***
## infection_any 0.02247 0.46979 0.048 0.962
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 128.93 on 176 degrees of freedom
## Residual deviance: 128.93 on 175 degrees of freedom
## AIC: 132.93
##
## Number of Fisher Scoring iterations: 4
m4 <- glm(NA_perfusion_event ~ GFR_MDRD, family = 'binomial', data = df2_corr)
summary(m4)
##
## Call:
## glm(formula = NA_perfusion_event ~ GFR_MDRD, family = "binomial",
## data = df2_corr)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.533940 0.655266 -3.867 0.00011 ***
## GFR_MDRD 0.009888 0.011130 0.888 0.37433
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 128.93 on 176 degrees of freedom
## Residual deviance: 128.16 on 175 degrees of freedom
## AIC: 132.16
##
## Number of Fisher Scoring iterations: 4How much are variables inter-correlated?
Open code
corrplot(cor(df2_corr, use = "pairwise.complete.obs", method = 'spearman'),
method = 'square')
## Warning in cor(df2_corr, use = "pairwise.complete.obs", method = "spearman"):
## the standard deviation is zero
## Warning in cor(df2_corr, use = "pairwise.complete.obs", method = "spearman"):
## the standard deviation is zero
path <- "gitignore/figures/sup_figure_1"
if (!file.exists(path)) {
pdf(path, width = 12, height = 12)
corrplot(cor(df2_corr, use = "pairwise.complete.obs", method = 'spearman'),
method = 'square')
dev.off()
}4.4 Multiple imputation
Open code
set.seed(2025)
init <- mice(data_model_priorImpute, maxit = 0)
init$method["perfusion_event"] <- "logreg"
data_imputed <- run(
expr = mice(
data_model_priorImpute,
method = init$method,
m = 80
),
path = "gitignore/run/data_imputed"
)
## Get the 1st imputed dataset
data_first <- complete(data_imputed, 'all')[1]$`1`5 Data points of nAB levels
Open code
plotac <- "figure_1"
path <- "gitignore/figures"
cole <- c(
"#E89C20", "#803800",
"#4C60FF", "#001070"
)
data_model_priorImpute <- data_model_priorImpute %>%
mutate(
group = factor(if_else(infliximab == 1, "infliximab", "control")),
Group = case_when(
infliximab == 1 & DGF == 0 ~ "IFX_DGF-",
infliximab == 1 & DGF == 1 ~ "IFX_DGF+",
infliximab == 0 & DGF == 0 ~ "ctrl_DGF-",
infliximab == 0 & DGF == 1 ~ "ctrl_DGF+",
)
)
p1 <- data_model_priorImpute %>%
ggplot(aes(x = Group, y = GPL_BC_log2, color = Group)) +
geom_boxplot(outlier.shape = NA, fill = NA, width = 0.8) +
geom_beeswarm(alpha = 0.5, cex = 2.3, size = 1.4) +
scale_color_manual(values = cole) +
# theme(axis.text.x = element_blank()) +
labs(
y = expression(log[2] ~ "(aCL IgG [" * mu * "g/ml])"),
x = NULL
) +
# scale_x_discrete(
# labels = c("", "nevim", "n" ,'n')
# ) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)
p2 <- data_model_priorImpute %>%
ggplot(aes(x = Group, y = MPL_BC_log2, color = Group)) +
geom_boxplot(outlier.shape = NA, fill = NA, width = 0.8) +
geom_beeswarm(alpha = 0.5, cex = 2.3, size = 1.4) +
scale_color_manual(values = cole) +
# theme(axis.text.x = element_blank()) +
labs(
y = expression(log[2] ~ "(aCL IgM [" * mu * "g/ml])"),
x = NULL
) +
# scale_x_discrete(
# labels = c("", "nevim", "n" ,'n')
# ) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)
data_model_priorImpute <- data_model_priorImpute %>%
mutate(
group = factor(if_else(infliximab == 1, "infliximab", "control")),
Group = case_when(
infliximab == 1 & infection_any == 0 ~ "IFX_non-infected",
infliximab == 1 & infection_any == 1 ~ "IFX_infected",
infliximab == 0 & infection_any == 0 ~ "ctrl_non-infected",
infliximab == 0 & infection_any == 1 ~ "ctrl_infected",
)
)
p3 <- data_model_priorImpute %>%
ggplot(aes(x = Group, y = GPE_dep_log2, color = Group)) +
geom_boxplot(outlier.shape = NA, fill = NA, width = 0.8) +
geom_beeswarm(alpha = 0.5, cex = 2.3, size = 1.4) +
scale_color_manual(values = cole) +
# theme(axis.text.x = element_blank()) +
labs(
y = expression(log[2] ~ "(aPE IgG dep [OD])"),
x = NULL
) +
# scale_x_discrete(
# labels = c("", "nevim", "n" ,'n')
# ) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)
p4 <- data_model_priorImpute %>%
ggplot(aes(x = Group, y = GPE_ind_log2, color = Group)) +
geom_boxplot(outlier.shape = NA, fill = NA, width = 0.8) +
geom_beeswarm(alpha = 0.5, cex = 2.3, size = 1.4) +
scale_color_manual(values = cole) +
# theme(axis.text.x = element_blank()) +
labs(
y = expression(log[2] ~ "(aPE IgG ind [OD])"),
x = NULL
) +
# scale_x_discrete(
# labels = c("", "nevim", "n" ,'n')
# ) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)
p5 <- data_model_priorImpute %>%
ggplot(aes(x = Group, y = MPE_dep_log2, color = Group)) +
geom_boxplot(outlier.shape = NA, fill = NA, width = 0.8) +
geom_beeswarm(alpha = 0.5, cex = 2.3, size = 1.4) +
scale_color_manual(values = cole) +
# theme(axis.text.x = element_blank()) +
labs(
y = expression(log[2] ~ "(aPE IgM dep [OD])"),
x = NULL
) +
# scale_x_discrete(
# labels = c("", "nevim", "n" ,'n')
# ) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)
p6 <- data_model_priorImpute %>%
ggplot(aes(x = Group, y = MPE_ind_log2, color = Group)) +
geom_boxplot(outlier.shape = NA, fill = NA, width = 0.8) +
geom_beeswarm(alpha = 0.5, cex = 2.3, size = 1.4) +
scale_color_manual(values = cole) +
# theme(axis.text.x = element_blank()) +
labs(
y = expression(log[2] ~ "(aPE IgM ind [OD])"),
x = NULL
) +
# scale_x_discrete(
# labels = c("", "nevim", "n" ,'n')
# ) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)
if (!file.exists(paste0(path, "/", plotac, ".pdf"))) {
assign(
plotac,
cowplot::plot_grid(p1, p2, p3, p4, p5, p6,
labels = c("A", "B", "C", "D", "E", "F"),
ncol = 2, nrow = , rel_heights = c(1, 1.1, 1.1)
)
)
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 6,
height = 10
)
}
get(plotac)6 Unadjsuted ORs for DGF
Definition of function
Open code
univar_mod <- function(dat,
outcome,
predictors,
family = "logistic",
level = 0.95,
rounding = 2
) {
N <- vector("double", length(predictors))
OR <- vector("double", length(predictors))
CI_L <- vector("double", length(predictors))
CI_U <- vector("double", length(predictors))
predictor <- vector("double", length(predictors))
for (i in 1:length(predictors)) {
data <- dat %>% dplyr::select(outcome,
all_of(unlist(strsplit(predictors[i], "\\*"))))
data <- na.omit(data)
N[i] <- nrow(data)
formula <- paste0(outcome, " ~ ", predictors[i])
if (family == "logistic") {
suppressMessages(suppressWarnings({
model <- glm(formula, data = data, family = "binomial"(link = "logit"))
OR[i] <- exp(coef(model)[length(coef(model))])
CI_L[i] <- exp(confint(model, level = level)[length(coef(model)), ])[1]
CI_U[i] <- exp(confint(model, level = level)[length(coef(model)), ])[2]
predictor[i] <- names(coef(model)[length(coef(model))])
result <- data.frame(
predictor,
OR = paste0(round(OR, rounding), ' [',round(CI_L, rounding), ', ',
round(CI_U, rounding),']'),
N
)
}))
} else if (family == "gaussian") {
suppressMessages(suppressWarnings({
model <- lm(formula, data = data)
OR[i] <- coef(model)[length(coef(model))]
CI_L[i] <- confint(model, level = level)[length(coef(model)), ][1]
CI_U[i] <- confint(model, level = level)[length(coef(model)), ][2]
predictor[i] <- names(coef(model)[length(coef(model))])
result <- data.frame(
predictor,
effect = paste0(round(OR, rounding), ' [',round(CI_L, rounding), ', ',
round(CI_U, rounding),']'),
N
)
}))
} else {
stop("incorrect family specification pyco", call. = FALSE)
}
}
return(result)
}
preds <- c(
"infliximab",
"GPL_BC_log2", "MPL_BC_log2",
"GPE_dep_log2", "GPE_ind_log2",
"MPE_dep_log2", "MPE_ind_log2",
"male_sex", "HLA_MM", "male_sex_donor", "KDPI",
"perfusion_event", "CIT", "rec_age", "DGF",
"infliximab*GPL_BC_log2", "infliximab*MPL_BC_log2",
"infliximab*GPE_dep_log2", "infliximab*GPE_ind_log2",
"infliximab*MPE_dep_log2", "infliximab*MPE_ind_log2"
)
preds_DGF <- c(
"infliximab",
"GPL_BC_log2", "MPL_BC_log2",
"GPE_dep_log2", "GPE_ind_log2",
"MPE_dep_log2", "MPE_ind_log2",
"male_sex", "HLA_MM", "male_sex_donor", "KDPI",
"perfusion_event", "CIT", "rec_age",
"infliximab*GPL_BC_log2", "infliximab*MPL_BC_log2",
"infliximab*GPE_dep_log2", "infliximab*GPE_ind_log2",
"infliximab*MPE_dep_log2", "infliximab*MPE_ind_log2"
)6.1 DGF
Open code
kableExtra::kable(
univar_mod(dat = data_model_priorImpute,
outcome = 'DGF',
predictors = preds_DGF,
family = 'logistic',
rounding = 2
) %>% rename(
`(R)OR` = `OR`
)
)
## Warning: Using an external vector in selections was deprecated in tidyselect 1.1.0.
## ℹ Please use `all_of()` or `any_of()` instead.
## # Was:
## data %>% select(outcome)
##
## # Now:
## data %>% select(all_of(outcome))
##
## See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.(R)OR: odds ratio (for main effects) or ratio of odds ratios (for interactions) [95% confidence interval]. N: number of observations.
| predictor | (R)OR | N |
|---|---|---|
| infliximab | 0.86 [0.46, 1.6] | 177 |
| GPL_BC_log2 | 1.08 [0.86, 1.34] | 177 |
| MPL_BC_log2 | 1.2 [0.98, 1.5] | 177 |
| GPE_dep_log2 | 1 [0.61, 1.61] | 177 |
| GPE_ind_log2 | 1.02 [0.66, 1.55] | 177 |
| MPE_dep_log2 | 1.08 [0.67, 1.73] | 177 |
| MPE_ind_log2 | 0.96 [0.54, 1.64] | 177 |
| male_sex | 2.2 [1.13, 4.43] | 177 |
| HLA_MM | 1.25 [0.97, 1.65] | 142 |
| male_sex_donor | 1.08 [0.58, 2.04] | 177 |
| KDPI | 1.01 [0.99, 1.02] | 177 |
| perfusion_event | 0.91 [0.46, 1.78] | 156 |
| CIT | 1.07 [1.02, 1.12] | 174 |
| rec_age | 0.99 [0.96, 1.02] | 177 |
| infliximab:GPL_BC_log2 | 1.84 [1.15, 3.02] | 177 |
| infliximab:MPL_BC_log2 | 1.52 [0.97, 2.43] | 177 |
| infliximab:GPE_dep_log2 | 1 [0.38, 2.62] | 177 |
| infliximab:GPE_ind_log2 | 1.04 [0.43, 2.45] | 177 |
| infliximab:MPE_dep_log2 | 2.32 [0.89, 6.21] | 177 |
| infliximab:MPE_ind_log2 | 1.59 [0.52, 5.04] | 177 |
6.2 GFR
Open code
kableExtra::kable(
univar_mod(dat = data_model_priorImpute,
outcome = 'GFR_MDRD',
predictors = preds,
family = 'gaussian',
rounding = 1
)
)Effect [95% confidennce interval] is shown and represents the estimated change in eGFR per one-unit increase in the predictor. For interaction terms, the effect quantifies the difference in the infliximab effect on eGFR at a given natural antibody (nAb) level vs its effect when the nAb level is halved. A 95% confidence interval including 0 suggests no significant modification of the infliximab effect by nAb levels. N: number of observations.
| predictor | effect | N |
|---|---|---|
| infliximab | -3.9 [-9.9, 2.1] | 177 |
| GPL_BC_log2 | 1.1 [-1, 3.2] | 177 |
| MPL_BC_log2 | -0.3 [-2.3, 1.6] | 177 |
| GPE_dep_log2 | 1.5 [-3.2, 6.1] | 177 |
| GPE_ind_log2 | -2.8 [-6.9, 1.3] | 177 |
| MPE_dep_log2 | 2.6 [-2, 7.1] | 177 |
| MPE_ind_log2 | 0.5 [-4.8, 5.8] | 177 |
| male_sex | -3.4 [-9.6, 2.7] | 177 |
| HLA_MM | -3.2 [-5.5, -1] | 142 |
| male_sex_donor | 4.8 [-1.3, 10.8] | 177 |
| KDPI | -0.2 [-0.3, -0.1] | 177 |
| perfusion_event | -6.8 [-13.1, -0.5] | 156 |
| CIT | 0.1 [-0.3, 0.6] | 174 |
| rec_age | -0.1 [-0.3, 0.2] | 177 |
| DGF | -15.9 [-21.8, -10] | 177 |
| infliximab:GPL_BC_log2 | -5.6 [-9.9, -1.3] | 177 |
| infliximab:MPL_BC_log2 | -4.7 [-8.6, -0.8] | 177 |
| infliximab:GPE_dep_log2 | 0.9 [-8.4, 10.1] | 177 |
| infliximab:GPE_ind_log2 | 0.8 [-7.5, 9.1] | 177 |
| infliximab:MPE_dep_log2 | -3.4 [-12.6, 5.8] | 177 |
| infliximab:MPE_ind_log2 | 2.3 [-8.3, 13] | 177 |
6.3 Infection
Open code
kableExtra::kable(
univar_mod(dat = data_model_priorImpute,
outcome = 'infection_any',
predictors = preds,
family = 'logistic'
)%>% rename(
`(R)OR` = `OR`
)
)(R)OR: odds ratio (for main effects) or ratio of odds ratios (for interactions) [95% confidence interval]. N: number of observations.
| predictor | (R)OR | N |
|---|---|---|
| infliximab | 1.11 [0.61, 2.02] | 177 |
| GPL_BC_log2 | 0.91 [0.73, 1.12] | 177 |
| MPL_BC_log2 | 0.94 [0.77, 1.14] | 177 |
| GPE_dep_log2 | 0.68 [0.42, 1.09] | 177 |
| GPE_ind_log2 | 0.66 [0.41, 1.02] | 177 |
| MPE_dep_log2 | 0.84 [0.53, 1.32] | 177 |
| MPE_ind_log2 | 1.09 [0.64, 1.84] | 177 |
| male_sex | 0.98 [0.53, 1.82] | 177 |
| HLA_MM | 0.88 [0.69, 1.11] | 142 |
| male_sex_donor | 0.87 [0.48, 1.58] | 177 |
| KDPI | 1.02 [1, 1.04] | 177 |
| perfusion_event | 0.75 [0.39, 1.43] | 156 |
| CIT | 0.93 [0.89, 0.98] | 174 |
| rec_age | 1 [0.97, 1.02] | 177 |
| DGF | 1.18 [0.63, 2.2] | 177 |
| infliximab:GPL_BC_log2 | 1.23 [0.79, 1.92] | 177 |
| infliximab:MPL_BC_log2 | 1.22 [0.82, 1.83] | 177 |
| infliximab:GPE_dep_log2 | 0.35 [0.12, 0.94] | 177 |
| infliximab:GPE_ind_log2 | 0.31 [0.1, 0.83] | 177 |
| infliximab:MPE_dep_log2 | 0.49 [0.19, 1.23] | 177 |
| infliximab:MPE_ind_log2 | 1 [0.35, 2.9] | 177 |
6.4 BKV
Open code
kableExtra::kable(
univar_mod(dat = data_model_priorImpute,
outcome = 'BKV_event_2',
predictors = preds,
family = 'logistic',
rounding = 2
) %>% rename(
`(R)OR` = `OR`)
)(R)OR: odds ratio (for main effects) or ratio of odds ratios (for interactions) [95% confidence interval]. N: number of observations.
| predictor | (R)OR | N |
|---|---|---|
| infliximab | 2.39 [1.15, 5.18] | 177 |
| GPL_BC_log2 | 0.83 [0.63, 1.07] | 177 |
| MPL_BC_log2 | 1.12 [0.89, 1.44] | 177 |
| GPE_dep_log2 | 0.72 [0.39, 1.27] | 177 |
| GPE_ind_log2 | 1.01 [0.59, 1.6] | 177 |
| MPE_dep_log2 | 1.13 [0.66, 1.93] | 177 |
| MPE_ind_log2 | 1.22 [0.65, 2.2] | 177 |
| male_sex | 1.71 [0.8, 3.84] | 177 |
| HLA_MM | 1.12 [0.84, 1.55] | 142 |
| male_sex_donor | 0.38 [0.18, 0.79] | 177 |
| KDPI | 0.99 [0.98, 1.01] | 177 |
| perfusion_event | 1.28 [0.57, 2.82] | 156 |
| CIT | 0.95 [0.89, 1] | 174 |
| rec_age | 1.03 [0.99, 1.06] | 177 |
| DGF | 1.36 [0.64, 2.84] | 177 |
| infliximab:GPL_BC_log2 | 1.34 [0.77, 2.41] | 177 |
| infliximab:MPL_BC_log2 | 1.1 [0.65, 1.86] | 177 |
| infliximab:GPE_dep_log2 | 1.57 [0.44, 6.14] | 177 |
| infliximab:GPE_ind_log2 | 0.49 [0.17, 1.33] | 177 |
| infliximab:MPE_dep_log2 | 1 [0.31, 3.22] | 177 |
| infliximab:MPE_ind_log2 | 1.37 [0.4, 5.26] | 177 |
7 DGF models
7.1 DGF by GPL_BC
7.1.1 Priors
Open code
# function to get prior
create_prior <- function(var, sigma, class = "b", coef = NULL) {
set_prior(paste0("normal(0, ", sigma, ")"), class = class, coef = coef)
}
scaling_unit <- 17.1.1.1 Main effects model
Open code
priors_main <- c(
create_prior("GPL_BC_log2",
2 / sd(data_model_priorImpute$GPL_BC_log2, na.rm = TRUE),
coef = "GPL_BC_log2"
),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"
),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"
),
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"
),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"
),
create_prior("male_sex",
4,
coef = "male_sex"
),
create_prior("perfusion_event",
4,
coef = "perfusion_event"
),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"
),
create_prior("infliximab",
4,
coef = "infliximab"
),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$DGF)), ", 10)"),
class = "Intercept"
)
)7.1.1.2 Non-linear penalized interaction model
Open code
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4,
coef = "male_sex"),
create_prior("perfusion_event",
4,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"),
create_prior("infliximab",
4,
coef = "infliximab"),
set_prior("student_t(3, 0, 0.6)", class = "sds",
coef = 's(GPL_BC_log2, bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 0.3)", class = "sds",
coef = 's(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$DGF)), ", 10)"),
class = "Intercept")
)7.1.2 Models
7.1.2.1 Main effects models
Open code
model_dgf_GPL_BC_main <- run(
expr = brm_multiple(
DGF ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
GPL_BC_log2,
family = bernoulli(),
data = data_imputed,
prior = priors_main,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_dgf_GPL_BC_main",
reuse = TRUE
)
summary(model_dgf_GPL_BC_main, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: bernoulli
## Links: mu = logit
## Formula: DGF ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + GPL_BC_log2
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept -0.75 0.48 -1.70 0.18 1.01 18087 26121
## male_sex 0.81 0.38 0.07 1.58 1.01 35270 27169
## Irec_ageM50 -0.02 0.02 -0.05 0.01 1.01 35275 27008
## male_sex_donor 0.10 0.37 -0.62 0.83 1.01 35510 27598
## IKDPIM50 0.01 0.01 -0.01 0.02 1.01 36654 26896
## ICITM15 0.08 0.03 0.02 0.13 1.02 11475 27045
## IHLA_MMM5 0.26 0.13 0.01 0.53 1.06 3602 18106
## perfusion_event -0.65 0.40 -1.45 0.13 1.06 3524 13012
## infliximab -0.33 0.35 -1.04 0.37 1.01 37331 27918
## GPL_BC_log2 0.05 0.13 -0.20 0.29 1.01 37266 27873
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_dgf_GPL_BC_main)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 1.41170525720746) b GPL_BC_log2
## normal(0, 0.280307006032291) b ICITM15
## normal(0, 1.38219051128263) b IHLA_MMM5
## normal(0, 0.0970980394231448) b IKDPIM50
## normal(0, 4) b infliximab
## normal(0, 0.190589762164436) b Irec_ageM50
## normal(0, 4) b male_sex
## normal(0, 4) b male_sex_donor
## normal(0, 4) b perfusion_event
## normal(-0.667829372575656, 10) Intercept
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
tr <- round(exp(fixef(model_dgf_GPL_BC_main, robust = TRUE)[-1, c(1,3,4)]), 2)
colnames(tr)[1] <- 'OR'
kableExtra::kable(tr)infliximab treatment and log2-transformed anti-cardiolipin IgG (GPL_BC_log2), on delayed graft function (DGF), without interaction terms. The odds ratio (OR) represents the estimated change in the odds of DGF per one-unit increase in the predictor. OR: odds ratio; Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 2.25 | 1.07 | 4.87 |
| Irec_ageM50 | 0.98 | 0.95 | 1.01 |
| male_sex_donor | 1.11 | 0.54 | 2.28 |
| IKDPIM50 | 1.01 | 0.99 | 1.02 |
| ICITM15 | 1.08 | 1.02 | 1.14 |
| IHLA_MMM5 | 1.30 | 1.01 | 1.70 |
| perfusion_event | 0.52 | 0.23 | 1.14 |
| infliximab | 0.72 | 0.35 | 1.45 |
| GPL_BC_log2 | 1.05 | 0.81 | 1.34 |
7.1.2.2 Non-linear interaction model
Open code
model_dgf_GPL_BC_interaction_NL <- run(
expr = brm_multiple(
DGF ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(GPL_BC_log2, bs = 'ps', k = 5) +
s(GPL_BC_log2, by = infliximab, bs = 'ps', k = 5),
family = bernoulli(),
data = data_imputed,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_dgf_GPL_BC_interaction_NL",
reuse = TRUE
)
summary(model_dgf_GPL_BC_interaction_NL, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: bernoulli
## Links: mu = logit
## Formula: DGF ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(GPL_BC_log2, bs = "ps", k = 5) + s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sGPL_BC_log2_1) 0.83 0.61 0.05 2.95 1.02
## sds(sGPL_BC_log2infliximab_1) 0.23 0.21 0.01 1.16 1.01
## Bulk_ESS Tail_ESS
## sds(sGPL_BC_log2_1) 14045 12820
## sds(sGPL_BC_log2infliximab_1) 27968 14350
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Intercept -0.88 0.49 -1.87 0.07 1.02 14612
## male_sex 0.97 0.40 0.20 1.80 1.01 35062
## Irec_ageM50 -0.02 0.02 -0.06 0.01 1.01 34006
## male_sex_donor 0.29 0.39 -0.47 1.06 1.01 34337
## IKDPIM50 0.01 0.01 -0.01 0.03 1.01 34534
## ICITM15 0.08 0.03 0.03 0.14 1.02 8750
## IHLA_MMM5 0.31 0.14 0.05 0.60 1.06 3297
## perfusion_event -0.75 0.43 -1.61 0.07 1.08 2768
## infliximab 0.02 3.90 -7.66 7.65 1.02 12394
## sGPL_BC_log2_1 -1.27 1.52 -4.37 2.91 1.01 19570
## sGPL_BC_log2:infliximab_1 2.30 2.41 -2.36 7.02 1.02 13785
## sGPL_BC_log2:infliximab_2 -2.66 1.62 -5.80 0.53 1.01 14601
## Tail_ESS
## Intercept 29212
## male_sex 26720
## Irec_ageM50 27092
## male_sex_donor 26886
## IKDPIM50 27506
## ICITM15 25453
## IHLA_MMM5 11332
## perfusion_event 9621
## infliximab 18177
## sGPL_BC_log2_1 15385
## sGPL_BC_log2:infliximab_1 20359
## sGPL_BC_log2:infliximab_2 22043
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_dgf_GPL_BC_interaction_NL)
## prior class
## (flat) b
## normal(0, 0.280307006032291) b
## normal(0, 1.38219051128263) b
## normal(0, 0.0970980394231448) b
## normal(0, 4) b
## normal(0, 0.190589762164436) b
## normal(0, 4) b
## normal(0, 4) b
## normal(0, 4) b
## (flat) b
## (flat) b
## (flat) b
## normal(-0.667829372575656, 10) Intercept
## student_t(3, 0, 2.5) sds
## student_t(3, 0, 0.6) sds
## student_t(3, 0, 0.3) sds
## coef group resp dpar nlpar lb ub
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sGPL_BC_log2_1
## sGPL_BC_log2:infliximab_1
## sGPL_BC_log2:infliximab_2
##
## 0
## s(GPL_BC_log2, bs = "ps", k = 5) 0
## s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5) 0
## source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## default
## user
## user
tr2 <- round(exp(fixef(model_dgf_GPL_BC_interaction_NL,
robust = TRUE)[-c(1,9:12), c(1,3,4)]), 2)
antibody_seq <- quantile(data_model_priorImpute$GPL_BC_log2,
probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
`male_sex` = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_dgf_GPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get odds ratio for infliximab effect across antibody values
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_GPL_BC_log2_int <- quantile(
exp((log(prediction$p95) - log(prediction$p05))/scaling_unit),
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_GPL_BC_log2_int, 2))
row.names(tr2)[8] <- 'infliximab:GPL_BC_log2'
colnames(tr2)[1] <- '(R)OR'
kableExtra::kable(tr2)GPL_BC_log2) and infliximab treatment on delayed graft function (DGF), while accounting for other covariates. Effects are presented as odds ratios (OR), with the last row reporting the ratio of odds ratios (ROR). The ROR represents the estimated ratio of infliximab’s treatment effect at the 95th versus the 5th percentile of anti-cardiolipin IgG, quantifying the interaction effect.Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| (R)OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 2.64 | 1.23 | 6.02 |
| Irec_ageM50 | 0.98 | 0.94 | 1.01 |
| male_sex_donor | 1.34 | 0.62 | 2.88 |
| IKDPIM50 | 1.01 | 0.99 | 1.03 |
| ICITM15 | 1.09 | 1.03 | 1.15 |
| IHLA_MMM5 | 1.36 | 1.05 | 1.83 |
| perfusion_event | 0.47 | 0.20 | 1.07 |
| infliximab:GPL_BC_log2 | 46.56 | 4.36 | 610.02 |
7.1.3 Visualisation
Extract posterior draws
Open code
antibody_perc <- quantile(data_model_priorImpute$GPL_BC_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_dgf_GPL_BC_interaction_NL,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
GPL_BC_log2 = data_prediction$GPL_BC_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control"))) %>%
ggplot(aes(x = GPL_BC_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 1),
breaks = c(seq(0, 1, by = 0.2))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
labs(x = expression(log[2]~"(aCL IgG ["*mu*"g/ml])"), y = "DGF risk") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 0),
aes(x = GPL_BC_log2),
sides = "b",
color = "black",
linewidth = 0.12,
inherit.aes = FALSE
) +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 1),
aes(x = GPL_BC_log2),
sides = "t",
color = "black",
linewidth = 0.12,
inherit.aes = FALSE
) +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -3.861561 4.949819
tr <- posterior_epred(
model_dgf_GPL_BC_interaction_NL,
newdata = data_prediction)
tr_ctrl <- (logit(tr[,c(ncol(tr)/2)]) - logit(tr[,c(1)])) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (logit(tr[,c(ncol(tr))]) - logit(tr[,c(ncol(tr)/2)+1]))/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_GPL_BC_log2 = tr_ctrl,
b_GPL_BC_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = exp(b_GPL_BC_log2),
infliximab = exp(b_GPL_BC_log2_infliximab)) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(1)
CIS
## control infliximab
## 2.5% 0.5 1.2
## 97.5% 1.1 3.2
## 50% 0.8 1.9
## 0.1% 0.4 0.9
## 99.9% 1.4 4.8
xpos <- 10
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aCL IgG on DGF risk (OR))",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(1/20, 20)) +
scale_x_continuous(transform = 'log2',
breaks = c(1/16, 1/4, 1, 4 ,16),
labels = c("1/16", "1/4", "1", "4", "16")) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 240
xseq <- c(1/64, 1/8, 1, 8, 64, 512)
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
antibody_seq
## 5% 25% 50% 75% 95%
## -1.8016683 -0.7449060 -0.1046076 0.8504991 2.5318211
antibody_seq**2
## 5% 25% 50% 75% 95%
## 3.24600871 0.55488501 0.01094276 0.72334876 6.41011830
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_dgf_GPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## p05 p25 p50 p75 p95
## 2.5% 0.03 0.13 0.27 0.60 1.38
## 97.5% 0.49 0.80 1.25 3.22 30.32
## 50% 0.13 0.34 0.59 1.37 6.24
## 0.1% 0.01 0.07 0.17 0.37 0.60
## 99.9% 1.02 1.28 1.93 5.41 82.13
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'GPL_BC_percentile') %>%
ggplot(aes(y = GPL_BC_percentile, x = value, fill = GPL_BC_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on DGF risk (odds ratio)",
y = 'Percentile of aCL IgG value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(1/300, 1150)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
scale_x_continuous(transform = 'log2',
breaks = c(xseq),
labels = c("1/64", "1/8", "1", "8", "64", '512')) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Odds ratio: ", CIS[3,5]),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Odds ratio: ", CIS[3,4]),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Odds ratio: ", CIS[3,3]),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", CIS[1,5], ", ", CIS[2,5], "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", CIS[1,4], ", ", CIS[2,4], "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", CIS[1,3], ", ", CIS[2,3], "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) 7.1.3.1 Figure merged
Open code
plotac <- 'figure_2'
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}7.2 DGF by MPL_BC
7.2.1 Priors
7.2.1.1 Main effects model
Open code
priors_main <- c(
create_prior("IMPL_BC_log2M2",
2 / sd(data_model_priorImpute$MPL_BC_log2, na.rm = TRUE),
coef = "IMPL_BC_log2M2"
),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"
),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"
),
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"
),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"
),
create_prior("male_sex",
4,
coef = "male_sex"
),
create_prior("perfusion_event",
4,
coef = "perfusion_event"
),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"
),
create_prior("infliximab",
4,
coef = "infliximab"
),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$DGF)), ", 10)"),
class = "Intercept"
)
)7.2.1.2 Non-linear penalized interaction model
Open code
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4,
coef = "male_sex"),
create_prior("perfusion_event",
4,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"),
create_prior("infliximab",
4,
coef = "infliximab"),
set_prior("student_t(3, 0, 0.6)", class = "sds",
coef = 's(I(MPL_BC_log2 - 2), bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 0.3)", class = "sds",
coef = 's(I(MPL_BC_log2 - 2), by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$DGF)), ", 10)"),
class = "Intercept")
)7.2.2 Models
7.2.2.1 Main effects models
Open code
set.seed(2025)
model_dgf_MPL_BC_main <- run(
expr = brm_multiple(
DGF ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
I(MPL_BC_log2 - 2),
family = bernoulli(),
data = data_imputed,
prior = priors_main,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_dgf_MPL_BC_main",
reuse = TRUE
)
summary(model_dgf_MPL_BC_main, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: bernoulli
## Links: mu = logit
## Formula: DGF ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + I(MPL_BC_log2 - 2)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept -0.88 0.48 -1.85 0.05 1.02 14414 25568
## male_sex 0.89 0.39 0.14 1.69 1.01 35387 28013
## Irec_ageM50 -0.02 0.02 -0.06 0.01 1.01 37218 27652
## male_sex_donor 0.14 0.37 -0.59 0.87 1.01 36459 27773
## IKDPIM50 0.01 0.01 -0.01 0.02 1.01 36554 27839
## ICITM15 0.07 0.03 0.02 0.13 1.02 11114 26679
## IHLA_MMM5 0.25 0.13 -0.00 0.52 1.06 3433 12047
## perfusion_event -0.61 0.41 -1.45 0.19 1.07 3180 11578
## infliximab -0.24 0.36 -0.97 0.48 1.01 35927 27005
## IMPL_BC_log2M2 0.20 0.12 -0.04 0.44 1.01 35829 26440
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_dgf_MPL_BC_main)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 0.280307006032291) b ICITM15
## normal(0, 1.38219051128263) b IHLA_MMM5
## normal(0, 0.0970980394231448) b IKDPIM50
## normal(0, 1.27934317633706) b IMPL_BC_log2M2
## normal(0, 4) b infliximab
## normal(0, 0.190589762164436) b Irec_ageM50
## normal(0, 4) b male_sex
## normal(0, 4) b male_sex_donor
## normal(0, 4) b perfusion_event
## normal(-0.667829372575656, 10) Intercept
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
tr <- round(exp(fixef(model_dgf_MPL_BC_main, robust = TRUE)[-1, c(1,3,4)]), 2)
colnames(tr)[1] <- 'OR'
kableExtra::kable(tr)infliximab treatment and log2-transformed anti-cardiolipin IgM (MPL_BC_log2), on delayed graft function (DGF), without interaction terms. The odds ratio (OR) represents the estimated change in the odds of DGF per one-unit increase in the predictor. OR: odds ratio; Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 2.44 | 1.15 | 5.40 |
| Irec_ageM50 | 0.98 | 0.95 | 1.01 |
| male_sex_donor | 1.15 | 0.56 | 2.40 |
| IKDPIM50 | 1.01 | 0.99 | 1.02 |
| ICITM15 | 1.08 | 1.02 | 1.14 |
| IHLA_MMM5 | 1.28 | 1.00 | 1.69 |
| perfusion_event | 0.55 | 0.23 | 1.21 |
| infliximab | 0.79 | 0.38 | 1.61 |
| IMPL_BC_log2M2 | 1.22 | 0.96 | 1.56 |
7.2.2.2 Non-linear interaction model
Open code
set.seed(2025)
model_dgf_MPL_BC_interaction_NL <- run(
expr = brm_multiple(
DGF ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(I(MPL_BC_log2-2), bs = 'ps', k = 5) +
s(I(MPL_BC_log2-2), by = infliximab, bs = 'ps', k = 5),
family = bernoulli(),
data = data_imputed,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_dgf_MPL_BC_interaction_NL",
reuse = TRUE
)
summary(model_dgf_MPL_BC_interaction_NL, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: bernoulli
## Links: mu = logit
## Formula: DGF ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(I(MPL_BC_log2 - 2), bs = "ps", k = 5) + s(I(MPL_BC_log2 - 2), by = infliximab, bs = "ps", k = 5)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sIMPL_BC_log2M2_1) 0.42 0.38 0.02 1.87 1.01
## sds(sIMPL_BC_log2M2infliximab_1) 0.22 0.20 0.01 1.07 1.00
## Bulk_ESS Tail_ESS
## sds(sIMPL_BC_log2M2_1) 22288 15370
## sds(sIMPL_BC_log2M2infliximab_1) 31518 16326
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Intercept -0.88 0.49 -1.86 0.05 1.02 18653
## male_sex 0.90 0.39 0.14 1.70 1.01 36356
## Irec_ageM50 -0.03 0.02 -0.06 0.01 1.01 34817
## male_sex_donor 0.23 0.38 -0.51 1.00 1.01 36879
## IKDPIM50 0.01 0.01 -0.01 0.02 1.01 35932
## ICITM15 0.07 0.03 0.02 0.13 1.02 15639
## IHLA_MMM5 0.25 0.13 0.00 0.53 1.06 3408
## perfusion_event -0.58 0.42 -1.42 0.23 1.08 2747
## infliximab -0.08 3.95 -7.77 7.71 1.02 12781
## sIMPL_BC_log2M2_1 0.36 1.27 -2.13 3.27 1.01 23892
## sIMPL_BC_log2M2:infliximab_1 1.13 2.95 -4.69 6.87 1.02 13362
## sIMPL_BC_log2M2:infliximab_2 -1.55 1.23 -4.00 0.82 1.01 16755
## Tail_ESS
## Intercept 28581
## male_sex 25744
## Irec_ageM50 26590
## male_sex_donor 27123
## IKDPIM50 27389
## ICITM15 24626
## IHLA_MMM5 11220
## perfusion_event 9277
## infliximab 17925
## sIMPL_BC_log2M2_1 20627
## sIMPL_BC_log2M2:infliximab_1 18672
## sIMPL_BC_log2M2:infliximab_2 23546
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_dgf_MPL_BC_interaction_NL)
## prior class
## (flat) b
## normal(0, 0.280307006032291) b
## normal(0, 1.38219051128263) b
## normal(0, 0.0970980394231448) b
## normal(0, 4) b
## normal(0, 0.190589762164436) b
## normal(0, 4) b
## normal(0, 4) b
## normal(0, 4) b
## (flat) b
## (flat) b
## (flat) b
## normal(-0.667829372575656, 10) Intercept
## student_t(3, 0, 2.5) sds
## student_t(3, 0, 0.6) sds
## student_t(3, 0, 0.3) sds
## coef group resp dpar nlpar
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sIMPL_BC_log2M2_1
## sIMPL_BC_log2M2:infliximab_1
## sIMPL_BC_log2M2:infliximab_2
##
##
## s(I(MPL_BC_log2 - 2), bs = "ps", k = 5)
## s(I(MPL_BC_log2 - 2), by = infliximab, bs = "ps", k = 5)
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## 0 default
## 0 user
## 0 user
tr2 <- round(exp(fixef(model_dgf_MPL_BC_interaction_NL, robust = TRUE)[-c(1,9:12), c(1,3,4)]), 2)
antibody_seq <- quantile(data_model_priorImpute$MPL_BC_log2, probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`MPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_dgf_MPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get odds ratio for infliximab effect across antibody values
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_MPL_BC_log2_int <- quantile(exp((log(prediction$p95) - log(prediction$p05))/scaling_unit),
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_MPL_BC_log2_int, 2))
row.names(tr2)[8] <- 'infliximab:MPL_BC_log2'
colnames(tr2)[1] <- '(R)OR'
kableExtra::kable(tr2)MPL_BC_log2) and infliximab treatment on delayed graft function (DGF), while accounting for other covariates. Effects are presented as odds ratios (OR), with the last row reporting the ratio of odds ratios (ROR). The ROR represents the estimated ratio of infliximab’s treatment effect at the 95th versus the 5th percentile of anti-cardiolipin IgG, quantifying the interaction effect.Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| (R)OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 2.47 | 1.14 | 5.49 |
| Irec_ageM50 | 0.98 | 0.94 | 1.01 |
| male_sex_donor | 1.26 | 0.60 | 2.71 |
| IKDPIM50 | 1.01 | 0.99 | 1.02 |
| ICITM15 | 1.08 | 1.02 | 1.14 |
| IHLA_MMM5 | 1.29 | 1.00 | 1.70 |
| perfusion_event | 0.56 | 0.24 | 1.26 |
| infliximab:MPL_BC_log2 | 12.18 | 1.07 | 165.59 |
7.2.3 Visualisation - penalized non-linear effect
Extract posterior draws
Open code
antibody_perc <- quantile(data_model_priorImpute$MPL_BC_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`MPL_BC_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_dgf_MPL_BC_interaction_NL,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
MPL_BC_log2 = data_prediction$MPL_BC_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control"))) %>%
ggplot(aes(x = MPL_BC_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 1),
breaks = c(seq(0, 1, by = 0.2))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
labs(x = expression(log[2]~"(aCL IgM ["*mu*"g/ml])"), y = "DGF risk") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 0),
aes(x = MPL_BC_log2),
sides = "b",
color = "black",
size = 0.12,
inherit.aes = FALSE
) +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 1),
aes(x = MPL_BC_log2),
sides = "t",
color = "black",
size = 0.12,
inherit.aes = FALSE
) +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -5.532591 5.416829
tr <- posterior_epred(
model_dgf_MPL_BC_interaction_NL,
newdata = data_prediction)
tr_ctrl <- (logit(tr[,c(ncol(tr)/2)]) - logit(tr[,c(1)])) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (logit(tr[,c(ncol(tr))]) - logit(tr[,c(ncol(tr)/2)+1]))/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_MPL_BC_log2 = tr_ctrl,
b_MPL_BC_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = exp(b_MPL_BC_log2),
infliximab = exp(b_MPL_BC_log2_infliximab)) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## control infliximab
## 2.5% 0.63 1.04
## 97.5% 1.36 2.44
## 50% 0.94 1.54
## 0.1% 0.47 0.81
## 99.9% 1.75 3.30
xpos <- 10
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aCL IgM on DGF risk (OR))",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(1/20, 20)) +
scale_x_continuous(transform = 'log2',
breaks = c(1/16, 1/4, 1, 4 ,16),
labels = c("1/16", "1/4", "1", "4", "16")) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 240
xseq <- c(1/64, 1/8, 1, 8, 64, 512)
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
antibody_seq
## 5% 25% 50% 75% 95%
## -0.3963058 1.0933124 2.0432905 2.9421729 4.5810923
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`MPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_dgf_MPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## p05 p25 p50 p75 p95
## 2.5% 0.05 0.19 0.37 0.52 0.66
## 97.5% 0.94 1.15 1.61 2.85 12.59
## 50% 0.23 0.48 0.77 1.22 2.79
## 0.1% 0.02 0.11 0.24 0.32 0.28
## 99.9% 2.07 1.85 2.43 4.75 31.56
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'MPL_BC_percentile') %>%
ggplot(aes(y = MPL_BC_percentile, x = value, fill = MPL_BC_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on DGF risk (odds ratio)",
y = 'Percentile of aCL IgM value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(1/300, 1000)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
scale_x_continuous(transform = 'log2',
breaks = c(xseq),
labels = c("1/64", "1/8", "1", "8", "64", '512')) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Odds ratio: ", CIS[3,5]),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Odds ratio: ", CIS[3,4]),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Odds ratio: ", CIS[3,3]),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", CIS[1,5], ", ", CIS[2,5], "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", CIS[1,4], ", ", CIS[2,4], "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", CIS[1,3], ", ", CIS[2,3], "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) 7.2.3.1 Figure merged
Open code
plotac <- 'sup_figure_3'
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}8 Infection models
8.1 Infection by GPE_dep
8.1.1 Priors
8.1.1.1 Main effects model
Open code
priors_main <- c(
create_prior("IGPE_dep_log2P2",
2 / sd(data_model_priorImpute$GPE_dep_log2, na.rm = TRUE),
coef = "IGPE_dep_log2P2"
),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"
),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"
),
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"
),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"
),
create_prior("male_sex",
4,
coef = "male_sex"
),
create_prior("perfusion_event",
4,
coef = "perfusion_event"
),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"
),
create_prior("infliximab",
4,
coef = "infliximab"
),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$infection_any)), ", 10)"),
class = "Intercept"
)
)8.1.1.2 Non-linear penalized interaction model
Open code
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4,
coef = "male_sex"),
create_prior("perfusion_event",
4,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"),
create_prior("infliximab",
4,
coef = "infliximab"),
set_prior("student_t(3, 0, 0.6)", class = "sds",
coef = 's(I(GPE_dep_log2 + 2), bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 0.3)", class = "sds",
coef = 's(I(GPE_dep_log2 + 2), by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$infection_any)), ", 10)"),
class = "Intercept")
)8.1.2 Models
8.1.2.1 Main effects models
Open code
model_infection_any_GPE_dep_main <- run(
expr = brm_multiple(
infection_any ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
I(GPE_dep_log2 + 2),
family = bernoulli(),
data = data_imputed,
prior = priors_main,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_infection_any_GPE_dep_main",
reuse = TRUE
)
summary(model_infection_any_GPE_dep_main, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: bernoulli
## Links: mu = logit
## Formula: infection_any ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + I(GPE_dep_log2 + 2)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept -1.20 0.47 -2.17 -0.30 1.03 8357 25111
## male_sex 0.28 0.36 -0.43 1.01 1.01 35581 26492
## Irec_ageM50 -0.03 0.02 -0.06 0.01 1.01 34812 27578
## male_sex_donor 0.22 0.36 -0.48 0.92 1.01 35747 27955
## IKDPIM50 0.03 0.01 0.02 0.05 1.00 31156 26870
## ICITM15 -0.10 0.03 -0.16 -0.04 1.01 21925 27001
## IHLA_MMM5 -0.27 0.13 -0.53 -0.04 1.05 3743 18243
## perfusion_event -0.04 0.40 -0.83 0.74 1.07 2925 12861
## infliximab 0.40 0.35 -0.27 1.09 1.01 36151 28346
## IGPE_dep_log2P2 -0.55 0.28 -1.11 -0.02 1.01 35008 27707
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_infection_any_GPE_dep_main)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 0.280307006032291) b ICITM15
## normal(0, 3.05433848490195) b IGPE_dep_log2P2
## normal(0, 1.38219051128263) b IHLA_MMM5
## normal(0, 0.0970980394231448) b IKDPIM50
## normal(0, 4) b infliximab
## normal(0, 0.190589762164436) b Irec_ageM50
## normal(0, 4) b male_sex
## normal(0, 4) b male_sex_donor
## normal(0, 4) b perfusion_event
## normal(-0.307484699747961, 10) Intercept
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
tr <- round(exp(fixef(model_infection_any_GPE_dep_main, robust = TRUE)[-1, c(1,3,4)]), 2)
colnames(tr)[1] <- 'OR'
kableExtra::kable(tr)infliximab treatment and log2-transformed co-factor-dependent phosphatidylethanolamine IgG (GPE_dep_log2), on infection risk, without interaction terms. The odds ratio (OR) represents the estimated change in the odds of infection per one-unit increase in the predictor. OR: odds ratio; Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 1.32 | 0.65 | 2.76 |
| Irec_ageM50 | 0.97 | 0.94 | 1.01 |
| male_sex_donor | 1.24 | 0.62 | 2.51 |
| IKDPIM50 | 1.03 | 1.02 | 1.05 |
| ICITM15 | 0.91 | 0.86 | 0.96 |
| IHLA_MMM5 | 0.76 | 0.59 | 0.97 |
| perfusion_event | 0.96 | 0.44 | 2.09 |
| infliximab | 1.49 | 0.77 | 2.97 |
| IGPE_dep_log2P2 | 0.58 | 0.33 | 0.98 |
8.1.2.2 Non-linear interaction model
Open code
model_infection_any_GPE_dep_interaction_NL <- run(
expr = brm_multiple(
infection_any ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(I(GPE_dep_log2+2), bs = 'ps', k = 5) +
s(I(GPE_dep_log2+2), by = infliximab, bs = 'ps', k = 5),
family = bernoulli(),
data = data_imputed,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_infection_any_GPE_dep_interaction_NL",
reuse = TRUE
)
summary(model_infection_any_GPE_dep_interaction_NL, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Warning: There were 1 divergent transitions after warmup. Increasing
## adapt_delta above 0.95 may help. See
## http://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
## Family: bernoulli
## Links: mu = logit
## Formula: infection_any ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(I(GPE_dep_log2 + 2), bs = "ps", k = 5) + s(I(GPE_dep_log2 + 2), by = infliximab, bs = "ps", k = 5)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sIGPE_dep_log2P2_1) 0.39 0.36 0.02 1.78 1.01
## sds(sIGPE_dep_log2P2infliximab_1) 0.22 0.21 0.01 1.20 1.00
## Bulk_ESS Tail_ESS
## sds(sIGPE_dep_log2P2_1) 23011 16212
## sds(sIGPE_dep_log2P2infliximab_1) 29739 16611
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## Intercept -0.96 0.47 -1.89 -0.05 1.02
## male_sex 0.20 0.37 -0.53 0.93 1.01
## Irec_ageM50 -0.03 0.02 -0.06 0.01 1.01
## male_sex_donor 0.15 0.36 -0.57 0.87 1.01
## IKDPIM50 0.03 0.01 0.01 0.05 1.01
## ICITM15 -0.10 0.03 -0.16 -0.04 1.01
## IHLA_MMM5 -0.27 0.12 -0.53 -0.03 1.05
## perfusion_event 0.02 0.41 -0.77 0.83 1.07
## infliximab 0.01 3.96 -7.77 7.88 1.02
## sIGPE_dep_log2P2_1 -0.01 1.21 -2.46 2.72 1.01
## sIGPE_dep_log2P2:infliximab_1 -1.54 2.40 -6.31 3.14 1.02
## sIGPE_dep_log2P2:infliximab_2 1.73 1.92 -2.01 5.47 1.01
## Bulk_ESS Tail_ESS
## Intercept 10823 27696
## male_sex 35504 26209
## Irec_ageM50 34966 27068
## male_sex_donor 36837 27583
## IKDPIM50 33808 25857
## ICITM15 17002 25866
## IHLA_MMM5 3867 19114
## perfusion_event 2911 11736
## infliximab 12595 17936
## sIGPE_dep_log2P2_1 24856 21147
## sIGPE_dep_log2P2:infliximab_1 14000 20327
## sIGPE_dep_log2P2:infliximab_2 14554 20883
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_infection_any_GPE_dep_interaction_NL)
## prior class
## (flat) b
## normal(0, 0.280307006032291) b
## normal(0, 1.38219051128263) b
## normal(0, 0.0970980394231448) b
## normal(0, 4) b
## normal(0, 0.190589762164436) b
## normal(0, 4) b
## normal(0, 4) b
## normal(0, 4) b
## (flat) b
## (flat) b
## (flat) b
## normal(-0.307484699747961, 10) Intercept
## student_t(3, 0, 2.5) sds
## student_t(3, 0, 0.6) sds
## student_t(3, 0, 0.3) sds
## coef group resp dpar
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sIGPE_dep_log2P2_1
## sIGPE_dep_log2P2:infliximab_1
## sIGPE_dep_log2P2:infliximab_2
##
##
## s(I(GPE_dep_log2 + 2), bs = "ps", k = 5)
## s(I(GPE_dep_log2 + 2), by = infliximab, bs = "ps", k = 5)
## nlpar lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## 0 default
## 0 user
## 0 user
tr2 <- round(exp(fixef(model_infection_any_GPE_dep_interaction_NL,
robust = TRUE)[-c(1,9:12), c(1,3,4)]), 3)
antibody_seq <- quantile(data_model_priorImpute$GPE_dep_log2,
probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPE_dep_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_infection_any_GPE_dep_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get odds ratio for infliximab effect across antibody values
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_GPE_dep_log2_int <- quantile(
exp((log(prediction$p95) - log(prediction$p05))/scaling_unit),
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_GPE_dep_log2_int, 3))
row.names(tr2)[8] <- 'infliximab:GPE_dep_log2'
colnames(tr2)[1] <- '(R)OR'
kableExtra::kable(tr2)GPE_dep_log2) and infliximab treatment on infection risk, while accounting for other covariates. Effects are presented as odds ratios (OR), with the last row reporting the ratio of odds ratios (ROR). The ROR represents the estimated ratio of infliximab’s treatment effect at the 95th versus the 5th percentile of aPE-dep IgG, quantifying the interaction effect.Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| (R)OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 1.220 | 0.590 | 2.539 |
| Irec_ageM50 | 0.972 | 0.938 | 1.006 |
| male_sex_donor | 1.166 | 0.568 | 2.392 |
| IKDPIM50 | 1.034 | 1.015 | 1.054 |
| ICITM15 | 0.905 | 0.851 | 0.957 |
| IHLA_MMM5 | 0.763 | 0.589 | 0.969 |
| perfusion_event | 1.018 | 0.463 | 2.299 |
| infliximab:GPE_dep_log2 | 0.097 | 0.008 | 0.995 |
8.1.3 Visualisation - penalized non-linear effect
Extract posterior draws
Open code
antibody_perc <- quantile(data_model_priorImpute$GPE_dep_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPE_dep_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_infection_any_GPE_dep_interaction_NL,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
GPE_dep_log2 = data_prediction$GPE_dep_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control"))) %>%
ggplot(aes(x = GPE_dep_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 1),
breaks = c(seq(0, 1, by = 0.2))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
labs(x = expression(log[2]~"(aPE IgG dep [OD])"), y = "Infection risk") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 0),
aes(x = GPE_dep_log2),
sides = "b",
color = "black",
size = 0.12,
inherit.aes = FALSE
) +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 1),
aes(x = GPE_dep_log2),
sides = "t",
color = "black",
size = 0.12,
inherit.aes = FALSE
) +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -3.6438562 0.4162993
tr <- posterior_epred(
model_infection_any_GPE_dep_interaction_NL,
newdata = data_prediction)
tr_ctrl <- (logit(tr[,c(ncol(tr)/2)]) - logit(tr[,c(1)])) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (logit(tr[,c(ncol(tr))]) - logit(tr[,c(ncol(tr)/2)+1]))/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_GPE_dep_log2 = tr_ctrl,
b_GPE_dep_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = exp(b_GPE_dep_log2),
infliximab = exp(b_GPE_dep_log2_infliximab)) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## control infliximab
## 2.5% 0.44 0.11
## 97.5% 2.37 0.79
## 50% 0.99 0.32
## 0.1% 0.27 0.05
## 99.9% 4.28 1.33
xpos <- 10
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aPE IgG dep on infection risk (OR)",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(1/20, 20)) +
scale_x_continuous(transform = 'log2',
breaks = c(1/16, 1/4, 1, 4 ,16),
labels = c("1/16", "1/4", "1", "4", "16")) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 240
xseq <- c(1/64, 1/8, 1, 8, 64, 512)
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
antibody_seq
## 5% 25% 50% 75% 95%
## -3.134163 -2.666576 -2.392137 -2.005782 -1.039488
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPE_dep_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_infection_any_GPE_dep_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>% round(3)
CIS
## p05 p25 p50 p75 p95
## 2.5% 1.147 1.005 0.824 0.492 0.066
## 97.5% 12.692 5.193 3.466 2.425 1.754
## 50% 3.731 2.260 1.676 1.097 0.361
## 0.1% 0.588 0.657 0.561 0.310 0.023
## 99.9% 24.985 8.400 5.455 3.839 4.295
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'GPE_dep_percentile') %>%
ggplot(aes(y = GPE_dep_percentile, x = value, fill = GPE_dep_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on infection risk (odds ratio)",
y = 'Percentile of aPE IgG dep value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(1/300, 1000)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
scale_x_continuous(transform = 'log2',
breaks = c(xseq),
labels = c("1/64", "1/8", "1", "8", "64", '512')) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Odds ratio: ", round(CIS[3,5], 2)),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Odds ratio: ", round(CIS[3,4], 2)),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Odds ratio: ", round(CIS[3,3], 2)),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Odds ratio: ", round(CIS[3,2],2 )),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Odds ratio: ", round(CIS[3,1], 2)),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", round(CIS[1,5], 2), ", ",
round(CIS[2,5], 2), "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", round(CIS[1,4], 2), ", ",
round(CIS[2,4], 2), "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", round(CIS[1,3], 2), ", ",
round(CIS[2,3], 2), "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", round(CIS[2,2], 2), "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", round(CIS[1,1], 2), ", ",
round(CIS[2,1], 2), "]"),
color = cole[1] ) 8.1.3.1 Figure merged
Open code
plotac <- 'sup_figure_7'
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}8.2 Infection by GPE_ind
8.2.1 Priors
8.2.1.1 Main effects model
Open code
priors_main <- c(
create_prior("IGPE_ind_log2P3",
2 / sd(data_model_priorImpute$GPE_ind_log2, na.rm = TRUE),
coef = "IGPE_ind_log2P3"
),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"
),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"
),
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"
),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"
),
create_prior("male_sex",
4,
coef = "male_sex"
),
create_prior("perfusion_event",
4,
coef = "perfusion_event"
),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"
),
create_prior("infliximab",
4,
coef = "infliximab"
),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$infection_any)), ", 10)"),
class = "Intercept"
)
)8.2.1.2 Non-linear penalized interaction model
Open code
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4,
coef = "male_sex"),
create_prior("perfusion_event",
4,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"),
create_prior("infliximab",
4,
coef = "infliximab"),
set_prior("student_t(3, 0, 0.6)", class = "sds",
coef = 's(I(GPE_ind_log2 + 3), bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 0.3)", class = "sds",
coef = 's(I(GPE_ind_log2 + 3), by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$infection_any)), ", 10)"),
class = "Intercept")
)8.2.2 Models
8.2.2.1 Main effects models
Open code
model_infection_any_GPE_ind_main <- run(
expr = brm_multiple(
infection_any ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
I(GPE_ind_log2 + 3),
family = bernoulli(),
data = data_imputed,
prior = priors_main,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_infection_any_GPE_ind_main",
reuse = TRUE
)
summary(model_infection_any_GPE_ind_main, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: bernoulli
## Links: mu = logit
## Formula: infection_any ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + I(GPE_ind_log2 + 3)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept -0.98 0.45 -1.90 -0.12 1.02 11019 25593
## male_sex 0.27 0.36 -0.44 1.00 1.01 37004 28448
## Irec_ageM50 -0.02 0.02 -0.06 0.01 1.01 35806 28429
## male_sex_donor 0.21 0.36 -0.48 0.92 1.01 36893 27040
## IKDPIM50 0.03 0.01 0.01 0.05 1.01 33713 27071
## ICITM15 -0.09 0.03 -0.15 -0.04 1.01 20286 25862
## IHLA_MMM5 -0.27 0.12 -0.52 -0.03 1.05 4283 14455
## perfusion_event -0.00 0.40 -0.79 0.80 1.07 2779 11061
## infliximab 0.33 0.35 -0.34 1.03 1.01 35569 27304
## IGPE_ind_log2P3 -0.42 0.25 -0.94 0.04 1.01 39171 26823
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_infection_any_GPE_ind_main)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 0.280307006032291) b ICITM15
## normal(0, 2.72256264350783) b IGPE_ind_log2P3
## normal(0, 1.38219051128263) b IHLA_MMM5
## normal(0, 0.0970980394231448) b IKDPIM50
## normal(0, 4) b infliximab
## normal(0, 0.190589762164436) b Irec_ageM50
## normal(0, 4) b male_sex
## normal(0, 4) b male_sex_donor
## normal(0, 4) b perfusion_event
## normal(-0.307484699747961, 10) Intercept
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
tr <- round(exp(fixef(model_infection_any_GPE_ind_main, robust = TRUE)[-1, c(1,3,4)]), 2)
colnames(tr)[1] <- 'OR'
kableExtra::kable(tr)infliximab treatment and log2-transformed co-factor-independent phosphatidylethanolamine IgG (GPE_ind_log2), on infection risk, without interaction terms. The odds ratio (OR) represents the estimated change in the odds of infection per one-unit increase in the predictor. OR: odds ratio; Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 1.32 | 0.64 | 2.71 |
| Irec_ageM50 | 0.98 | 0.94 | 1.01 |
| male_sex_donor | 1.23 | 0.62 | 2.51 |
| IKDPIM50 | 1.03 | 1.01 | 1.05 |
| ICITM15 | 0.91 | 0.86 | 0.96 |
| IHLA_MMM5 | 0.77 | 0.59 | 0.97 |
| perfusion_event | 1.00 | 0.45 | 2.23 |
| infliximab | 1.39 | 0.71 | 2.79 |
| IGPE_ind_log2P3 | 0.66 | 0.39 | 1.05 |
8.2.2.2 Non-linear interaction model
Open code
model_infection_any_GPE_ind_interaction_NL <- run(
expr = brm_multiple(
infection_any ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(I(GPE_ind_log2+3), bs = 'ps', k = 5) +
s(I(GPE_ind_log2+3), by = infliximab, bs = 'ps', k = 5),
family = bernoulli(),
data = data_imputed,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_infection_any_GPE_ind_interaction_NL",
reuse = TRUE
)
summary(model_infection_any_GPE_ind_interaction_NL, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: bernoulli
## Links: mu = logit
## Formula: infection_any ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(I(GPE_ind_log2 + 3), bs = "ps", k = 5) + s(I(GPE_ind_log2 + 3), by = infliximab, bs = "ps", k = 5)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sIGPE_ind_log2P3_1) 0.36 0.33 0.02 1.69 1.01
## sds(sIGPE_ind_log2P3infliximab_1) 0.22 0.21 0.01 1.14 1.00
## Bulk_ESS Tail_ESS
## sds(sIGPE_ind_log2P3_1) 20777 16750
## sds(sIGPE_ind_log2P3infliximab_1) 29345 15825
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## Intercept -1.01 0.47 -1.96 -0.12 1.03
## male_sex 0.23 0.37 -0.49 0.97 1.01
## Irec_ageM50 -0.02 0.02 -0.06 0.01 1.01
## male_sex_donor 0.20 0.36 -0.51 0.91 1.01
## IKDPIM50 0.03 0.01 0.01 0.05 1.01
## ICITM15 -0.10 0.03 -0.16 -0.04 1.01
## IHLA_MMM5 -0.27 0.13 -0.54 -0.03 1.05
## perfusion_event 0.06 0.42 -0.77 0.89 1.07
## infliximab 0.02 3.94 -7.59 7.86 1.02
## sIGPE_ind_log2P3_1 -0.00 0.94 -2.19 1.95 1.01
## sIGPE_ind_log2P3:infliximab_1 -1.90 2.38 -6.69 2.67 1.02
## sIGPE_ind_log2P3:infliximab_2 2.02 2.37 -2.61 6.62 1.02
## Bulk_ESS Tail_ESS
## Intercept 9152 25359
## male_sex 35120 26888
## Irec_ageM50 33206 26289
## male_sex_donor 34551 26083
## IKDPIM50 32183 26588
## ICITM15 16827 25092
## IHLA_MMM5 3866 13123
## perfusion_event 2824 11080
## infliximab 12055 17429
## sIGPE_ind_log2P3_1 25340 18221
## sIGPE_ind_log2P3:infliximab_1 13678 20478
## sIGPE_ind_log2P3:infliximab_2 13739 20092
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_infection_any_GPE_ind_interaction_NL)
## prior class
## (flat) b
## normal(0, 0.280307006032291) b
## normal(0, 1.38219051128263) b
## normal(0, 0.0970980394231448) b
## normal(0, 4) b
## normal(0, 0.190589762164436) b
## normal(0, 4) b
## normal(0, 4) b
## normal(0, 4) b
## (flat) b
## (flat) b
## (flat) b
## normal(-0.307484699747961, 10) Intercept
## student_t(3, 0, 2.5) sds
## student_t(3, 0, 0.6) sds
## student_t(3, 0, 0.3) sds
## coef group resp dpar
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sIGPE_ind_log2P3_1
## sIGPE_ind_log2P3:infliximab_1
## sIGPE_ind_log2P3:infliximab_2
##
##
## s(I(GPE_ind_log2 + 3), bs = "ps", k = 5)
## s(I(GPE_ind_log2 + 3), by = infliximab, bs = "ps", k = 5)
## nlpar lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## 0 default
## 0 user
## 0 user
tr2 <- round(exp(fixef(model_infection_any_GPE_ind_interaction_NL,
robust = TRUE)[-c(1,9:12), c(1,3,4)]), 2)
antibody_seq <- quantile(data_model_priorImpute$GPE_ind_log2,
probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPE_ind_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_infection_any_GPE_ind_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get odds ratio for infliximab effect across antibody values
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_GPE_ind_log2_int <- quantile(
exp((log(prediction$p95) - log(prediction$p05))/scaling_unit),
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_GPE_ind_log2_int, 4))
row.names(tr2)[8] <- 'infliximab:GPE_ind_log2'
colnames(tr2)[1] <- '(R)OR'
kableExtra::kable(tr2)GPE_ind_log2) and infliximab treatment on infection risk, while accounting for other covariates. Effects are presented as odds ratios (OR), with the last row reporting the ratio of odds ratios (ROR). The ROR represents the estimated ratio of infliximab’s treatment effect at the 95th versus the 5th percentile of aPE-ind IgG, quantifying the interaction effect.Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| (R)OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 1.2600 | 0.610 | 2.6400 |
| Irec_ageM50 | 0.9800 | 0.940 | 1.0100 |
| male_sex_donor | 1.2200 | 0.600 | 2.4900 |
| IKDPIM50 | 1.0300 | 1.010 | 1.0500 |
| ICITM15 | 0.9100 | 0.850 | 0.9600 |
| IHLA_MMM5 | 0.7600 | 0.590 | 0.9700 |
| perfusion_event | 1.0600 | 0.460 | 2.4300 |
| infliximab:GPE_ind_log2 | 0.0751 | 0.005 | 0.7543 |
8.2.3 Visualisation - penalized non-linear effect
Extract posterior draws
Open code
antibody_perc <- quantile(data_model_priorImpute$GPE_ind_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPE_ind_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_infection_any_GPE_ind_interaction_NL,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
GPE_ind_log2 = data_prediction$GPE_ind_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control"))) %>%
ggplot(aes(x = GPE_ind_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 1),
breaks = c(seq(0, 1, by = 0.2))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
labs(x = expression(log[2]~"(aPE IgG ind [OD])"), y = "Infection risk") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 0),
aes(x = GPE_ind_log2),
sides = "b",
color = "black",
size = 0.12,
inherit.aes = FALSE
) +
geom_rug(
data = data_model_priorImpute %>% filter(DGF == 1),
aes(x = GPE_ind_log2),
sides = "t",
color = "black",
size = 0.12,
inherit.aes = FALSE
) +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -3.86775220 -0.03283139
tr <- posterior_epred(
model_infection_any_GPE_ind_interaction_NL,
newdata = data_prediction)
tr_ctrl <- (logit(tr[,c(ncol(tr)/2)]) - logit(tr[,c(1)])) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (logit(tr[,c(ncol(tr))]) - logit(tr[,c(ncol(tr)/2)+1]))/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_GPE_ind_log2 = tr_ctrl,
b_GPE_ind_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = exp(b_GPE_ind_log2),
infliximab = exp(b_GPE_ind_log2_infliximab)) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## control infliximab
## 2.5% 0.53 0.09
## 97.5% 1.91 0.75
## 50% 1.02 0.30
## 0.1% 0.35 0.03
## 99.9% 2.76 1.17
xpos <- 10
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aPE IgG ind on infection risk (OR)",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(1/20, 20)) +
scale_x_continuous(transform = 'log2',
breaks = c(1/16, 1/4, 1, 4 ,16),
labels = c("1/16", "1/4", "1", "4", "16")) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 240
xseq <- c(1/64, 1/8, 1, 8, 64, 512)
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
antibody_seq
## 5% 25% 50% 75% 95%
## -3.654722 -3.411195 -3.164884 -2.708396 -1.490602
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPE_ind_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_infection_any_GPE_ind_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## p05 p25 p50 p75 p95
## 2.5% 1.11 1.01 0.85 0.45 0.03
## 97.5% 9.08 5.56 3.68 2.26 1.33
## 50% 3.12 2.34 1.75 1.02 0.23
## 0.1% 0.63 0.65 0.57 0.27 0.01
## 99.9% 16.77 9.12 5.86 3.60 3.26
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'GPE_ind_percentile') %>%
ggplot(aes(y = GPE_ind_percentile, x = value, fill = GPE_ind_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on infection risk (odds ratio)",
y = 'Percentile of aPE IgG ind value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(1/300, 1000)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
scale_x_continuous(transform = 'log2',
breaks = c(xseq),
labels = c("1/64", "1/8", "1", "8", "64", '512')) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Odds ratio: ", CIS[3,5]),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Odds ratio: ", CIS[3,4]),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Odds ratio: ", CIS[3,3]),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", CIS[1,5], ", ", CIS[2,5], "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", CIS[1,4], ", ", CIS[2,4], "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", CIS[1,3], ", ", CIS[2,3], "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) 8.2.3.1 Figure merged
Open code
plotac <- 'sup_figure_8'
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}9 GFR models
9.1 GFR_MDRD by GPL_BC
9.1.1 Priors
Open code
GFR_sd <- sd(data_model_priorImpute$GFR_MDRD)
GFR_sd
## [1] 20.257579.1.1.1 Main effects model
Open code
priors_main <- c(
create_prior("GPL_BC_log2",
GFR_sd*(2*GFR_sd) / sd(data_model_priorImpute$GPL_BC_log2, na.rm = TRUE),
coef = "GPL_BC_log2"
),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"
),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"
),
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"
),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"
),
create_prior("male_sex",
4*GFR_sd,
coef = "male_sex"
),
create_prior("perfusion_event",
4*GFR_sd,
coef = "perfusion_event"
),
create_prior("male_sex_donor",
4*GFR_sd,
coef = "male_sex_donor"
),
create_prior("infliximab",
4*GFR_sd,
coef = "infliximab"
),
set_prior(paste0("normal(", mean(data_model_priorImpute$GFR_MDRD), ", 200)"),
class = "Intercept"
)
)9.1.1.2 Non-linear penalized interaction model
Open code
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4*GFR_sd,
coef = "male_sex"),
create_prior("perfusion_event",
4*GFR_sd,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4*GFR_sd,
coef = "male_sex_donor"),
create_prior("infliximab",
4*GFR_sd,
coef = "infliximab"),
set_prior("student_t(3, 0, 12)", class = "sds",
coef = 's(GPL_BC_log2, bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 6)", class = "sds",
coef = 's(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", mean(data_model_priorImpute$GFR_MDRD), ", 200)"),
class = "Intercept")
)9.1.2 Models
9.1.2.1 Main effects models
Open code
model_GFR_MDRD_GPL_BC_main <- run(
expr = brm_multiple(
GFR_MDRD ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
GPL_BC_log2,
family = student(),
data = data_imputed,
prior = priors_main,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_GFR_MDRD_GPL_BC_main",
reuse = TRUE
)
summary(model_GFR_MDRD_GPL_BC_main, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: student
## Links: mu = identity; sigma = identity; nu = identity
## Formula: GFR_MDRD ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + GPL_BC_log2
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 54.68 3.91 46.96 62.35 1.01 24831 27184
## male_sex -1.55 3.16 -7.77 4.77 1.01 37765 27484
## Irec_ageM50 0.06 0.15 -0.23 0.34 1.01 36648 28073
## male_sex_donor 1.35 3.10 -4.77 7.48 1.01 36660 26964
## IKDPIM50 -0.19 0.08 -0.34 -0.04 1.01 35386 27634
## ICITM15 0.23 0.22 -0.21 0.66 1.02 11422 26910
## IHLA_MMM5 -0.97 1.07 -3.11 1.11 1.06 3180 13261
## perfusion_event -5.76 3.35 -12.35 0.80 1.06 3549 13194
## infliximab -2.45 3.02 -8.43 3.38 1.01 37369 28011
## GPL_BC_log2 0.60 1.08 -1.52 2.67 1.01 36026 27839
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 18.53 1.23 16.10 21.01 1.01 31215 24031
## nu 18.84 10.62 6.38 55.52 1.00 32368 25991
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_GFR_MDRD_GPL_BC_main)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 579.319999877126) b GPL_BC_log2
## normal(0, 5.67833744497037) b ICITM15
## normal(0, 27.9998143727979) b IHLA_MMM5
## normal(0, 1.96696986241627) b IKDPIM50
## normal(0, 81.0302607180105) b infliximab
## normal(0, 3.86088452959197) b Irec_ageM50
## normal(0, 81.0302607180105) b male_sex
## normal(0, 81.0302607180105) b male_sex_donor
## normal(0, 81.0302607180105) b perfusion_event
## normal(51.900395480226, 200) Intercept
## gamma(2, 0.1) nu
## student_t(3, 0, 18) sigma
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
## 1 default
## 0 default
tr <- round(fixef(model_GFR_MDRD_GPL_BC_main, robust = TRUE)[-1, c(1,3,4)], 2)
colnames(tr)[1] <- 'Estimate'
kableExtra::kable(tr)infliximab treatment and log2-transformed anti-cardiolipin IgG (GPL_BC_log2), on estimated glomerular filtration rate (eGFR, GFR_MDRD), without interaction terms. Estimate represents the estimated change in eGFR per one-unit increase in the predictor. Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| Estimate | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | -1.55 | -7.77 | 4.77 |
| Irec_ageM50 | 0.06 | -0.23 | 0.34 |
| male_sex_donor | 1.35 | -4.77 | 7.48 |
| IKDPIM50 | -0.19 | -0.34 | -0.04 |
| ICITM15 | 0.23 | -0.21 | 0.66 |
| IHLA_MMM5 | -0.97 | -3.11 | 1.11 |
| perfusion_event | -5.76 | -12.35 | 0.80 |
| infliximab | -2.45 | -8.43 | 3.38 |
| GPL_BC_log2 | 0.60 | -1.52 | 2.67 |
9.1.2.2 Non-linear interaction model
Open code
model_GFR_MDRD_GPL_BC_interaction_NL <- run(
expr = brm_multiple(
GFR_MDRD ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(GPL_BC_log2, bs = 'ps', k = 5) +
s(GPL_BC_log2, by = infliximab, bs = 'ps', k = 5),
family = student(),
data = data_imputed,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_GFR_MDRD_GPL_BC_interaction_NL",
reuse = TRUE
)
summary(model_GFR_MDRD_GPL_BC_interaction_NL, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: student
## Links: mu = identity; sigma = identity; nu = identity
## Formula: GFR_MDRD ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(GPL_BC_log2, bs = "ps", k = 5) + s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sGPL_BC_log2_1) 9.59 6.65 0.79 32.62 1.01
## sds(sGPL_BC_log2infliximab_1) 4.22 3.92 0.20 19.87 1.00
## Bulk_ESS Tail_ESS
## sds(sGPL_BC_log2_1) 17186 13787
## sds(sGPL_BC_log2infliximab_1) 34106 17300
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Intercept 55.59 3.87 47.89 63.25 1.01 34127
## male_sex -2.13 3.12 -8.38 4.01 1.01 45929
## Irec_ageM50 0.05 0.14 -0.23 0.33 1.01 45812
## male_sex_donor 0.08 3.13 -6.08 6.23 1.01 43251
## IKDPIM50 -0.19 0.08 -0.35 -0.04 1.01 40749
## ICITM15 0.23 0.22 -0.20 0.65 1.02 10278
## IHLA_MMM5 -1.19 1.06 -3.27 0.86 1.07 3216
## perfusion_event -5.52 3.35 -11.93 1.03 1.05 4240
## infliximab 1.75 79.08 -154.92 156.04 1.01 13750
## sGPL_BC_log2_1 18.26 13.84 -11.91 55.94 1.01 24018
## sGPL_BC_log2:infliximab_1 -19.27 45.54 -107.83 71.48 1.01 14101
## sGPL_BC_log2:infliximab_2 13.44 28.08 -41.91 69.30 1.01 14185
## Tail_ESS
## Intercept 28929
## male_sex 25866
## Irec_ageM50 27262
## male_sex_donor 27173
## IKDPIM50 28218
## ICITM15 26370
## IHLA_MMM5 13665
## perfusion_event 18675
## infliximab 19279
## sGPL_BC_log2_1 19589
## sGPL_BC_log2:infliximab_1 19727
## sGPL_BC_log2:infliximab_2 19762
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 18.01 1.22 15.59 20.53 1.01 35929 26058
## nu 17.93 10.20 6.13 52.20 1.00 37566 27925
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_GFR_MDRD_GPL_BC_interaction_NL)
## prior class
## (flat) b
## normal(0, 5.67833744497037) b
## normal(0, 27.9998143727979) b
## normal(0, 1.96696986241627) b
## normal(0, 81.0302607180105) b
## normal(0, 3.86088452959197) b
## normal(0, 81.0302607180105) b
## normal(0, 81.0302607180105) b
## normal(0, 81.0302607180105) b
## (flat) b
## (flat) b
## (flat) b
## normal(51.900395480226, 200) Intercept
## gamma(2, 0.1) nu
## student_t(3, 0, 18) sds
## student_t(3, 0, 12) sds
## student_t(3, 0, 6) sds
## student_t(3, 0, 18) sigma
## coef group resp dpar nlpar lb ub
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sGPL_BC_log2_1
## sGPL_BC_log2:infliximab_1
## sGPL_BC_log2:infliximab_2
##
## 1
## 0
## s(GPL_BC_log2, bs = "ps", k = 5) 0
## s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5) 0
## 0
## source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## default
## default
## user
## user
## default
tr2 <- round(fixef(model_GFR_MDRD_GPL_BC_interaction_NL,
robust = TRUE)[-c(1,9:12), c(1,3,4)], 2)
antibody_seq <- quantile(data_model_priorImpute$GPL_BC_log2,
probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get Estimate for infliximab effect across antibody values
prediction <- (
prediction_infliximab-
prediction_ctrl
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_GPL_BC_log2_int <- quantile(
(prediction$p95 - prediction$p05)/scaling_unit,
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_GPL_BC_log2_int, 2))
row.names(tr2)[8] <- 'infliximab:GPL_BC_log2'
kableExtra::kable(tr2)GPL_BC_log2) and infliximab treatment on estimated glomerular filtration rate (eGFR, GFR_MDRD), while accounting for other covariates. Estimate represents the estimated change in eGFR per one-unit increase in the predictor. The last row (infliximab:GPL_BC_log2) reports the difference in infliximab’s treatment effect at the 95th versus the 5th percentile of anti-cardiolipin IgG, quantifying the interaction effect. Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| Estimate | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | -2.13 | -8.38 | 4.01 |
| Irec_ageM50 | 0.05 | -0.23 | 0.33 |
| male_sex_donor | 0.08 | -6.08 | 6.23 |
| IKDPIM50 | -0.19 | -0.35 | -0.04 |
| ICITM15 | 0.23 | -0.20 | 0.65 |
| IHLA_MMM5 | -1.19 | -3.27 | 0.86 |
| perfusion_event | -5.52 | -11.93 | 1.03 |
| infliximab:GPL_BC_log2 | -25.18 | -43.66 | -6.75 |
9.1.3 Visualisation - penalized non-linear effect
Extract posterior draws
Open code
antibody_perc <- quantile(data_model_priorImpute$GPL_BC_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
GPL_BC_log2 = data_prediction$GPL_BC_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control")),
`Q2.5` = if_else(`Q2.5` < 0, 0, `Q2.5`)) %>%
ggplot(aes(x = GPL_BC_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 125),
breaks = c(seq(0, 125, by = 25))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
geom_point(data = data_model_priorImpute,
aes(x = GPL_BC_log2, y = GFR_MDRD, col = group, fill = group)) +
labs(x = expression(log[2]~"(aCL IgG ["*mu*"g/ml])"),
y = "GFR (mL/min/1.73 m²)") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size = 10),
axis.title=element_text(size = 12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -3.861561 4.949819
tr <- posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL,
newdata = data_prediction)
tr_ctrl <- (tr[,c(ncol(tr)/2)] - tr[,c(1)]) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (tr[,c(ncol(tr))] - tr[,c(ncol(tr)/2)+1])/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_GPL_BC_log2 = tr_ctrl,
b_GPL_BC_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = b_GPL_BC_log2,
infliximab = b_GPL_BC_log2_infliximab) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## control infliximab
## 2.5% -0.03 -6.95
## 97.5% 5.72 1.14
## 50% 2.82 -2.95
## 0.1% -1.60 -9.80
## 99.9% 7.62 4.11
xpos <- 20
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aCL IgG on GFR (mL/min/1.73 m²)",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(-20, 26)) +
geom_vline(xintercept = 0, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Estimate: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Estimate: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 30
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
prediction_infliximab-
prediction_ctrl
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(1)
CIS
## p05 p25 p50 p75 p95
## 2.5% -2.4 -4.8 -7.7 -14.1 -30.0
## 97.5% 17.9 8.8 4.5 -0.3 -5.1
## 50% 7.7 2.0 -1.7 -7.2 -17.4
## 0.1% -8.2 -9.1 -11.3 -18.0 -38.0
## 99.9% 23.8 13.0 8.3 3.6 2.0
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'GPL_BC_percentile') %>%
ggplot(aes(y = GPL_BC_percentile, x = value, fill = GPL_BC_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on GFR (mL/min/1.73 m²)",
y = 'Percentile of aCL IgG value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(-40, 40)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
geom_vline(xintercept = 0, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Estimate: ", CIS[3,5]),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Estimate: ", CIS[3,4]),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Estimate: ", CIS[3,3]),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Estimate: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Estimate: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", CIS[1,5], ", ", CIS[2,5], "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", CIS[1,4], ", ", CIS[2,4], "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", CIS[1,3], ", ", CIS[2,3], "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) 9.1.3.1 Figure merged
Open code
plotac <- 'sup_figure_4'
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}9.2 GFR_MDRD by MPL_BC
9.2.1 Priors
9.2.1.1 Main effects model
Open code
priors_main <- c(
create_prior("IMPL_BC_log2M2",
(2*GFR_sd) / sd(data_model_priorImpute$MPL_BC_log2, na.rm = TRUE),
coef = "IMPL_BC_log2M2"
),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"
),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"
),
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"
),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"
),
create_prior("male_sex",
4*GFR_sd,
coef = "male_sex"
),
create_prior("perfusion_event",
4*GFR_sd,
coef = "perfusion_event"
),
create_prior("male_sex_donor",
4*GFR_sd,
coef = "male_sex_donor"
),
create_prior("infliximab",
4*GFR_sd,
coef = "infliximab"
),
set_prior(paste0("normal(", mean(data_model_priorImpute$GFR_MDRD), ", 200)"),
class = "Intercept"
)
)9.2.1.2 Non-linear penalized interaction model
Open code
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4*GFR_sd,
coef = "male_sex"),
create_prior("perfusion_event",
4*GFR_sd,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4*GFR_sd,
coef = "male_sex_donor"),
create_prior("infliximab",
4*GFR_sd,
coef = "infliximab"),
set_prior("student_t(3, 0, 12)", class = "sds",
coef = 's(I(MPL_BC_log2 - 2), bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 6)", class = "sds",
coef = 's(I(MPL_BC_log2 - 2), by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", mean(data_model_priorImpute$GFR_MDRD), ", 200)"),
class = "Intercept")
)9.2.2 Models
9.2.2.1 Main effects models
Open code
model_GFR_MDRD_MPL_BC_main <- run(
expr = brm_multiple(
GFR_MDRD ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
I(MPL_BC_log2 - 2),
family = student(),
data = data_imputed,
prior = priors_main,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_GFR_MDRD_MPL_BC_main",
reuse = TRUE
)
summary(model_GFR_MDRD_MPL_BC_main, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: student
## Links: mu = identity; sigma = identity; nu = identity
## Formula: GFR_MDRD ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + I(MPL_BC_log2 - 2)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 55.75 3.99 47.95 63.59 1.02 15676 27265
## male_sex -2.00 3.18 -8.29 4.26 1.01 36988 27786
## Irec_ageM50 0.05 0.14 -0.23 0.34 1.01 36377 27272
## male_sex_donor 1.08 3.06 -5.00 7.17 1.01 36948 28496
## IKDPIM50 -0.19 0.08 -0.34 -0.03 1.01 35327 27152
## ICITM15 0.28 0.22 -0.16 0.70 1.02 11620 26888
## IHLA_MMM5 -0.97 1.07 -3.11 1.12 1.06 3340 11461
## perfusion_event -6.45 3.39 -13.09 0.22 1.05 3818 19112
## infliximab -3.15 3.07 -9.23 2.93 1.01 37419 27699
## IMPL_BC_log2M2 -0.98 0.99 -2.90 0.98 1.01 36441 28028
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 18.48 1.22 16.08 20.97 1.01 29092 24387
## nu 18.77 10.57 6.44 55.18 1.00 31124 26418
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_GFR_MDRD_MPL_BC_main)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 5.67833744497037) b ICITM15
## normal(0, 27.9998143727979) b IHLA_MMM5
## normal(0, 1.96696986241627) b IKDPIM50
## normal(0, 25.9163777815998) b IMPL_BC_log2M2
## normal(0, 81.0302607180105) b infliximab
## normal(0, 3.86088452959197) b Irec_ageM50
## normal(0, 81.0302607180105) b male_sex
## normal(0, 81.0302607180105) b male_sex_donor
## normal(0, 81.0302607180105) b perfusion_event
## normal(51.900395480226, 200) Intercept
## gamma(2, 0.1) nu
## student_t(3, 0, 18) sigma
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
## 1 default
## 0 default
tr <- round(fixef(model_GFR_MDRD_MPL_BC_main, robust = TRUE)[-1, c(1,3,4)], 2)
colnames(tr)[1] <- 'Estimate'
kableExtra::kable(tr)infliximab treatment and log2-transformed anti-cardiolipin IgM (MPL_BC_log2), on estimated glomerular filtration rate (eGFR, GFR_MDRD), without interaction terms. Estimate represents the estimated change in eGFR per one-unit increase in the predictor. Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| Estimate | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | -2.00 | -8.29 | 4.26 |
| Irec_ageM50 | 0.05 | -0.23 | 0.34 |
| male_sex_donor | 1.08 | -5.00 | 7.17 |
| IKDPIM50 | -0.19 | -0.34 | -0.03 |
| ICITM15 | 0.28 | -0.16 | 0.70 |
| IHLA_MMM5 | -0.97 | -3.11 | 1.12 |
| perfusion_event | -6.45 | -13.09 | 0.22 |
| infliximab | -3.15 | -9.23 | 2.93 |
| IMPL_BC_log2M2 | -0.98 | -2.90 | 0.98 |
9.2.2.2 Non-linear interaction model
Open code
model_GFR_MDRD_MPL_BC_interaction_NL <- run(
expr = brm_multiple(
GFR_MDRD ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(I(MPL_BC_log2-2), bs = 'ps', k = 5) +
s(I(MPL_BC_log2-2), by = infliximab, bs = 'ps', k = 5),
family = student(),
data = data_imputed,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 2000, warmup = 1900,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_GFR_MDRD_MPL_BC_interaction_NL",
reuse = TRUE
)
summary(model_GFR_MDRD_MPL_BC_interaction_NL, robust = TRUE)
## Warning: Parts of the model have not converged (some Rhats are > 1.05). Be
## careful when analysing the results! We recommend running more iterations and/or
## setting stronger priors.
## Family: student
## Links: mu = identity; sigma = identity; nu = identity
## Formula: GFR_MDRD ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(I(MPL_BC_log2 - 2), bs = "ps", k = 5) + s(I(MPL_BC_log2 - 2), by = infliximab, bs = "ps", k = 5)
## Data: data_imputed (Number of observations: 177)
## Draws: 320 chains, each with iter = 2000; warmup = 1900; thin = 1;
## total post-warmup draws = 32000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sIMPL_BC_log2M2_1) 5.48 5.15 0.24 26.01 1.01
## sds(sIMPL_BC_log2M2infliximab_1) 4.06 3.78 0.20 18.64 1.00
## Bulk_ESS Tail_ESS
## sds(sIMPL_BC_log2M2_1) 22894 18113
## sds(sIMPL_BC_log2M2infliximab_1) 30115 17762
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Intercept 55.26 3.96 47.56 63.03 1.01 17517
## male_sex -1.78 3.14 -8.01 4.43 1.01 46798
## Irec_ageM50 0.07 0.14 -0.22 0.35 1.01 46248
## male_sex_donor 0.55 3.08 -5.55 6.61 1.01 46056
## IKDPIM50 -0.18 0.08 -0.33 -0.03 1.01 44542
## ICITM15 0.28 0.22 -0.16 0.70 1.02 12810
## IHLA_MMM5 -1.02 1.07 -3.13 1.08 1.06 3228
## perfusion_event -6.94 3.37 -13.60 -0.32 1.05 3778
## infliximab 0.02 79.41 -154.70 156.08 1.02 14644
## sIMPL_BC_log2M2_1 -8.42 11.64 -34.46 19.33 1.01 26393
## sIMPL_BC_log2M2:infliximab_1 -16.06 57.67 -130.78 96.21 1.02 14804
## sIMPL_BC_log2M2:infliximab_2 11.92 19.62 -26.46 49.76 1.01 15212
## Tail_ESS
## Intercept 30328
## male_sex 26548
## Irec_ageM50 27384
## male_sex_donor 26969
## IKDPIM50 28281
## ICITM15 26355
## IHLA_MMM5 11257
## perfusion_event 13872
## infliximab 19342
## sIMPL_BC_log2M2_1 20425
## sIMPL_BC_log2M2:infliximab_1 19537
## sIMPL_BC_log2M2:infliximab_2 20207
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 18.31 1.22 15.93 20.78 1.01 35683 24148
## nu 19.59 10.89 6.60 56.82 1.00 38348 26532
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_GFR_MDRD_MPL_BC_interaction_NL)
## prior class
## (flat) b
## normal(0, 5.67833744497037) b
## normal(0, 27.9998143727979) b
## normal(0, 1.96696986241627) b
## normal(0, 81.0302607180105) b
## normal(0, 3.86088452959197) b
## normal(0, 81.0302607180105) b
## normal(0, 81.0302607180105) b
## normal(0, 81.0302607180105) b
## (flat) b
## (flat) b
## (flat) b
## normal(51.900395480226, 200) Intercept
## gamma(2, 0.1) nu
## student_t(3, 0, 18) sds
## student_t(3, 0, 12) sds
## student_t(3, 0, 6) sds
## student_t(3, 0, 18) sigma
## coef group resp dpar nlpar
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sIMPL_BC_log2M2_1
## sIMPL_BC_log2M2:infliximab_1
## sIMPL_BC_log2M2:infliximab_2
##
##
##
## s(I(MPL_BC_log2 - 2), bs = "ps", k = 5)
## s(I(MPL_BC_log2 - 2), by = infliximab, bs = "ps", k = 5)
##
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## 1 default
## 0 default
## 0 user
## 0 user
## 0 default
tr2 <- round(fixef(model_GFR_MDRD_MPL_BC_interaction_NL,
robust = TRUE)[-c(1,9:12), c(1,3,4)], 2)
antibody_seq <- quantile(data_model_priorImpute$MPL_BC_log2, probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`MPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_GFR_MDRD_MPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get Estimate for infliximab effect across antibody values
prediction <- (
prediction_infliximab-
prediction_ctrl
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_MPL_BC_log2_int <- quantile((prediction$p95 - prediction$p05)/scaling_unit,
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_MPL_BC_log2_int, 2))
row.names(tr2)[8] <- 'infliximab:MPL_BC_log2'
kableExtra::kable(tr2)MPL_BC_log2) and infliximab treatment on estimated glomerular filtration rate (eGFR, GFR_MDRD), while accounting for other covariates. Estimate represents the estimated change in eGFR per one-unit increase in the predictor. The last row (infliximab:MPL_BC_log2) reports the difference in infliximab’s treatment effect at the 95th versus the 5th percentile of anti-cardiolipin IgM, quantifying the interaction effect. Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| Estimate | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | -1.78 | -8.01 | 4.43 |
| Irec_ageM50 | 0.07 | -0.22 | 0.35 |
| male_sex_donor | 0.55 | -5.55 | 6.61 |
| IKDPIM50 | -0.18 | -0.33 | -0.03 |
| ICITM15 | 0.28 | -0.16 | 0.70 |
| IHLA_MMM5 | -1.02 | -3.13 | 1.08 |
| perfusion_event | -6.94 | -13.60 | -0.32 |
| infliximab:MPL_BC_log2 | -23.76 | -43.26 | -4.64 |
9.2.3 Visualisation - penalized non-linear effect
Extract posterior draws
Open code
antibody_perc <- quantile(data_model_priorImpute$MPL_BC_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`MPL_BC_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_GFR_MDRD_MPL_BC_interaction_NL,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
MPL_BC_log2 = data_prediction$MPL_BC_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control")),
`Q2.5` = if_else(`Q2.5` < 0, 0, `Q2.5`)) %>%
ggplot(aes(x = MPL_BC_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 125),
breaks = c(seq(0, 125, by = 25))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
geom_point(data = data_model_priorImpute,
aes(x = MPL_BC_log2, y = GFR_MDRD, col = group, fill = group)) +
labs(x = expression(log[2]~"(aCL IgM ["*mu*"g/ml])"), y = "GFR (mL/min/1.73 m²)") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -5.532591 5.416829
tr <- posterior_epred(
model_GFR_MDRD_MPL_BC_interaction_NL,
newdata = data_prediction)
tr_ctrl <- (tr[,c(ncol(tr)/2)] - tr[,c(1)]) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (tr[,c(ncol(tr))] - tr[,c(ncol(tr)/2)+1])/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_MPL_BC_log2 = tr_ctrl,
b_MPL_BC_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = (b_MPL_BC_log2),
infliximab = (b_MPL_BC_log2_infliximab)) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## control infliximab
## 2.5% -1.84 -5.99
## 97.5% 4.77 0.03
## 50% 1.46 -2.96
## 0.1% -4.09 -8.08
## 99.9% 6.97 2.08
xpos <- 15
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aCL IgM on GFR (mL/min/1.73 m²) ",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(-20, 20)) +
geom_vline(xintercept = 0, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Estimate: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Estimate: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 30
xseq <- c(1/64, 1/8, 1, 8, 64, 512)
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
antibody_seq
## 5% 25% 50% 75% 95%
## -0.3963058 1.0933124 2.0432905 2.9421729 4.5810923
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`MPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_GFR_MDRD_MPL_BC_interaction_NL,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
prediction_infliximab-
prediction_ctrl
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(1)
CIS
## p05 p25 p50 p75 p95
## 2.5% -3.1 -5.8 -9.5 -14.8 -28.6
## 97.5% 18.7 8.2 2.8 -0.5 -3.8
## 50% 7.7 1.1 -3.3 -7.7 -16.0
## 0.1% -10.1 -10.1 -13.0 -18.9 -35.7
## 99.9% 24.8 12.1 6.4 3.4 3.6
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'MPL_BC_percentile') %>%
ggplot(aes(y = MPL_BC_percentile, x = value, fill = MPL_BC_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on GFR (mL/min/1.73 m²)",
y = 'Percentile of aCL IgM value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(-40, 40)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
geom_vline(xintercept = 0, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Estimate: ", CIS[3,5]),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Estimate: ", CIS[3,4]),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Estimate: ", CIS[3,3]),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Estimate: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Estimate: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", CIS[1,5], ", ", CIS[2,5], "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", CIS[1,4], ", ", CIS[2,4], "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", CIS[1,3], ", ", CIS[2,3], "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) 9.2.3.1 Figure merged
Open code
plotac <- 'sup_figure_5'
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}10 Summarizing table
Open code
data_results_table_OR <- data.frame(
outcome = c('DGF', 'DGF', 'infecition', 'infection'),
antibody = c('aCL IgG', 'aCL IgM', 'aPE-dep IgG', 'aPE-ind IgG'),
IFX_OR_p05 = c('0.13 [0.03, 0.49]',
'0.23 [0.05, 0.94]',
'3.73 [1.15, 12.69]',
'3.12 [1.11, 9.08]'
),
IFX_OR_p25 = c('0.34 [0.13, 0.80]',
'0.48 [0.19, 1.15]',
'2.26 [1.005, 5.19]',
'2.34 [1.01, 5.56]'
),
IFX_OR_p50 = c('0.59 [0.27, 1.25]',
'0.77 [0.37, 1.61]',
'1.68 [0.82, 3.47]',
'1.75 [0.85, 3.68]'
),
IFX_OR_p75 = c('1.37 [0.60, 3.22]',
'1.22 [0.52, 2.85]',
'1.10 [0.49, 2.42]',
'1.02 [0.45, 2.26]'
),
IFX_OR_p95 = c('6.24 [1.38, 30.32]',
'2.79 [0.66, 12.59]',
'0.36 [0.07, 1.75]',
'0.23 [0.03, 1.33]'
),
p95_per_p05_ROR = c('46.6 [4.4, 610.0]',
'12.8 [1.1, 166.6]',
'0.097 [0.008, 0.995]',
'0.08 [0.005, 0.75]'
)
)
data_results_table_cont <- data.frame(
outcome = c('eGFR', 'eGFR'),
antibody = c('aCL IgG', 'aCL IgM'),
IFX_eff_p05 = c('7.7 [-2.4, 17.9]',
'7.7 [-3.1, 18.7]'),
IFX_eff_p25 = c('2.0 [-4.8, 8.8]',
'1.1 [-5.8, 8.2]'),
IFX_eff_p50 = c('-1.7 [-7.7, 4.5]',
'-3.3 [-9.5, 2.8]'),
IFX_eff_p75 = c('-7.2 [-14.1, -0.3]',
'-7.7 [-14.8, -0.5]'),
IFX_eff_p95 = c('-17.4 [-30.0, -5.1]',
'-16.0 [-28.6, -3.8]'),
p95_p05_DE = c('-25.2 [-43.7, -6.8]',
'-24.8 [-43.2, -4.6]')
)
kableExtra::kable(data_results_table_OR)
kableExtra::kable(data_results_table_cont)antibody) levels and infliximab (IFX) treatment on the specified outcome. The antibody include anti-cardiolipin IgG or IgM (aCL IgG or IgM) and co-factor (ind)dependent anti-phosphatidylethanolamine (aPE-dep IgG and aPE-ind IgG respectively). IFX treatment effects (odds ratio [OR] for logistic models, absolute effect [eff] for robust regression) are reported at the 5th, 25th, 50th, 75th, and 95th percentiles of nAb levels, each with [95% credible interval]. Interaction magnitudes are expressed as the ratio of odds ratios (ROR) for the IFX effect at the 95th vs. 5th percentile of the nAb level (p95_per_p05_ROR) in logistic models (A) and as the difference in treatment effects at the 95th minus 5th percentile (p95_p05_DE) in robust regression (B), both with [95% credible intervals]
| outcome | antibody | IFX_OR_p05 | IFX_OR_p25 | IFX_OR_p50 | IFX_OR_p75 | IFX_OR_p95 | p95_per_p05_ROR |
|---|---|---|---|---|---|---|---|
| DGF | aCL IgG | 0.13 [0.03, 0.49] | 0.34 [0.13, 0.80] | 0.59 [0.27, 1.25] | 1.37 [0.60, 3.22] | 6.24 [1.38, 30.32] | 46.6 [4.4, 610.0] |
| DGF | aCL IgM | 0.23 [0.05, 0.94] | 0.48 [0.19, 1.15] | 0.77 [0.37, 1.61] | 1.22 [0.52, 2.85] | 2.79 [0.66, 12.59] | 12.8 [1.1, 166.6] |
| infecition | aPE-dep IgG | 3.73 [1.15, 12.69] | 2.26 [1.005, 5.19] | 1.68 [0.82, 3.47] | 1.10 [0.49, 2.42] | 0.36 [0.07, 1.75] | 0.097 [0.008, 0.995] |
| infection | aPE-ind IgG | 3.12 [1.11, 9.08] | 2.34 [1.01, 5.56] | 1.75 [0.85, 3.68] | 1.02 [0.45, 2.26] | 0.23 [0.03, 1.33] | 0.08 [0.005, 0.75] |
| outcome | antibody | IFX_eff_p05 | IFX_eff_p25 | IFX_eff_p50 | IFX_eff_p75 | IFX_eff_p95 | p95_p05_DE |
|---|---|---|---|---|---|---|---|
| eGFR | aCL IgG | 7.7 [-2.4, 17.9] | 2.0 [-4.8, 8.8] | -1.7 [-7.7, 4.5] | -7.2 [-14.1, -0.3] | -17.4 [-30.0, -5.1] | -25.2 [-43.7, -6.8] |
| eGFR | aCL IgM | 7.7 [-3.1, 18.7] | 1.1 [-5.8, 8.2] | -3.3 [-9.5, 2.8] | -7.7 [-14.8, -0.5] | -16.0 [-28.6, -3.8] | -24.8 [-43.2, -4.6] |
11 GFR: Mediation and AB-subgroup analysis
11.1 GPL_BC subgroup, DGF mediation
11.1.1 Define the subgroups
Open code
GPL_median <- median(data_model_priorImpute$GPL_BC_log2)
GPL_median
## [1] -0.1046076
data_imputed_highGPL <- data.frame(subset(
data_first,
subset = data_first$GPL_BC_log2 >= GPL_median
))
data_imputed_lowGPL <- subset(
data_first,
subset = data_first$GPL_BC_log2 < GPL_median
)11.1.2 Priors
Open code
create_prior <- function(var, sigma, class = "b") {
set_prior(paste0("normal(0, ", sigma, ")"), class = class, coef = var)
}
GFR_sd <- sd(data_model_priorImpute$GFR_MDRD)
GFR_sd
## [1] 20.25757
priors_subset <- c(
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_model_priorImpute$rec_age, na.rm = TRUE)
),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE)
),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_model_priorImpute$KDPI, na.rm = TRUE)
),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_model_priorImpute$CIT, na.rm = TRUE)
),
create_prior("male_sex",
4*GFR_sd
),
create_prior("perfusion_event",
4*GFR_sd
),
create_prior("male_sex_donor",
4*GFR_sd
),
create_prior("infliximab",
4*GFR_sd
),
set_prior(paste0("normal(", mean(data_model_priorImpute$GFR_MDRD), ", 200)"),
class = "Intercept"
)
)
create_prior <- function(var, sigma, class = "b", resp = 'GFR_MDRD') {
set_prior(paste0("normal(0, ", sigma, ")"), class = class, coef = var, resp = resp)
}
priors_mediation <- c(
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_model_priorImpute$rec_age, na.rm = TRUE)
),
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
resp = 'DGF'
),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE)
),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
resp = 'DGF'
),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_model_priorImpute$KDPI, na.rm = TRUE)
),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
resp = 'DGF'
),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_model_priorImpute$CIT, na.rm = TRUE)
),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_model_priorImpute$CIT, na.rm = TRUE),
resp = 'DGF'
),
create_prior("male_sex",
4*GFR_sd
),
create_prior("male_sex",
4*GFR_sd,
resp = 'DGF'
),
create_prior("perfusion_event",
4*GFR_sd
),
create_prior("perfusion_event",
4*GFR_sd,
resp = 'DGF'
),
create_prior("male_sex_donor",
4*GFR_sd
),
create_prior("male_sex_donor",
4*GFR_sd,
resp = 'DGF'
),
create_prior("infliximab",
4*GFR_sd
),
create_prior("infliximab",
4*GFR_sd,
resp = 'DGF'
),
create_prior("DGF",
4*GFR_sd
)
)11.1.3 GPL subgroup models
Open code
model_GFR_MDRD_GPLsubset_low <- run(
expr = brm(
GFR_MDRD ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
# GPL_BC_log2 +
infliximab,
family = student(),
data = data_imputed_lowGPL,
prior = priors_subset,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 6000, warmup = 2000,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_GFR_MDRD_GPLsubset_low",
reuse = TRUE
)
summary(model_GFR_MDRD_GPLsubset_low)
## Family: student
## Links: mu = identity; sigma = identity; nu = identity
## Formula: GFR_MDRD ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab
## Data: data_imputed_lowGPL (Number of observations: 88)
## Draws: 4 chains, each with iter = 6000; warmup = 2000; thin = 1;
## total post-warmup draws = 16000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 53.64 6.14 41.70 65.79 1.00 12937 12099
## male_sex -4.62 4.63 -13.77 4.51 1.00 15868 12555
## Irec_ageM50 0.11 0.22 -0.32 0.54 1.00 15296 12996
## male_sex_donor -1.07 4.42 -9.76 7.58 1.00 16194 12207
## IKDPIM50 -0.07 0.12 -0.30 0.16 1.00 13512 12251
## ICITM15 0.27 0.34 -0.39 0.93 1.00 15680 11690
## IHLA_MMM5 -2.69 1.56 -5.71 0.42 1.00 14006 11874
## perfusion_event -10.42 4.51 -19.28 -1.59 1.00 15569 11275
## infliximab 7.95 4.34 -0.56 16.52 1.00 15538 12635
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 18.38 1.72 15.18 21.98 1.00 13123 10365
## nu 21.59 13.33 5.59 55.41 1.00 12924 10419
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
model_GFR_MDRD_GPLsubset_high <- run(
expr = brm(
GFR_MDRD ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
#GPL_BC_log2 +
infliximab,
family = student(),
data = data_imputed_highGPL,
prior = priors_subset,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 6000, warmup = 2000,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_GFR_MDRD_GPLsubset_high",
reuse = TRUE
)
summary(model_GFR_MDRD_GPLsubset_high)
## Family: student
## Links: mu = identity; sigma = identity; nu = identity
## Formula: GFR_MDRD ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab
## Data: data_imputed_highGPL (Number of observations: 89)
## Draws: 4 chains, each with iter = 6000; warmup = 2000; thin = 1;
## total post-warmup draws = 16000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 57.76 4.73 48.55 67.15 1.00 16997 12841
## male_sex -0.24 4.23 -8.56 8.08 1.00 15905 12133
## Irec_ageM50 -0.04 0.19 -0.43 0.34 1.00 16471 12080
## male_sex_donor 1.38 4.40 -7.30 10.07 1.00 15460 12845
## IKDPIM50 -0.30 0.11 -0.51 -0.10 1.00 14493 12398
## ICITM15 0.20 0.28 -0.36 0.75 1.00 15661 12193
## IHLA_MMM5 -0.52 1.45 -3.37 2.30 1.00 15902 12189
## perfusion_event -1.74 4.57 -10.80 7.29 1.00 13721 11816
## infliximab -13.28 4.16 -21.38 -5.08 1.00 15993 12761
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 17.66 1.67 14.50 21.12 1.00 12364 9869
## nu 22.05 13.62 5.26 56.17 1.00 12209 10212
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).11.1.4 Mediation
Prepare table
Open code
# Model for the mediator DGF
m1 <- bf(
DGF ~ scale(male_sex) +
scale(rec_age) +
scale(male_sex_donor) +
scale(KDPI) +
scale(CIT) +
scale(HLA_MM) +
scale(perfusion_event) +
infliximab,
family = bernoulli(link = "logit")
)
# Model for the outcome GFR
m2 <- bf(
GFR_MDRD ~ scale(male_sex) +
scale(rec_age) +
scale(male_sex_donor) +
scale(KDPI) +
scale(CIT) +
scale(HLA_MM) +
scale(perfusion_event) +
infliximab +
DGF,
family = student()
)
## Joint model - Low GPL_BC
model_GFR_GPL_mediate_low <- run(
expr = brm(
m1 + m2 + set_rescor(FALSE),
data = data_imputed_lowGPL,
priors_mediation,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 6000, warmup = 2000,
control = list(adapt_delta = 0.95), refresh = 0),
path = "gitignore/run/model_GFR_GPL_mediate_low",
reuse = TRUE
)
## Joint model - high GPL_BC
model_GFR_GPL_mediate_high <- run(
expr = brm(
m1 + m2 + set_rescor(FALSE),
data = data_imputed_highGPL,
priors_mediation,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 6000, warmup = 2000,
control = list(adapt_delta = 0.95), refresh = 0),
path = "gitignore/run/model_GFR_GPL_mediate_high",
reuse = TRUE
)
post_fix_low <- as.data.frame(model_GFR_GPL_mediate_low) %>%
select(b_GFRMDRD_Intercept, b_GFRMDRD_infliximab, b_GFRMDRD_DGF,
b_DGF_Intercept, b_DGF_infliximab) %>%
mutate(predicted_DGF_ctrl = inv_logit(b_DGF_Intercept),
predicted_DGF_infx = inv_logit(b_DGF_Intercept + b_DGF_infliximab)) %>%
mutate(
indirect_pred_ctrl = b_GFRMDRD_Intercept +
(b_GFRMDRD_infliximab * mean(data_imputed_lowGPL$infliximab) ) +
(b_GFRMDRD_DGF * predicted_DGF_ctrl),
indirect_pred_infx = b_GFRMDRD_Intercept +
(b_GFRMDRD_infliximab * mean(data_imputed_lowGPL$infliximab) ) +
(b_GFRMDRD_DGF * predicted_DGF_infx),
) %>%
mutate(
`Direct Effect (ADE)` = b_GFRMDRD_infliximab,
`Indirect Effect (ACME)` = indirect_pred_infx - indirect_pred_ctrl,
`Mediator Effect` = b_GFRMDRD_DGF,
`Total Effect` = (
(indirect_pred_infx - indirect_pred_ctrl) + b_GFRMDRD_infliximab
)
) %>%
select(`Direct Effect (ADE)`:`Total Effect`)
med_eff_low <- sapply(
post_fix_low,
function(p) quantile(p, probs = c(0.5, 0.025, 0.975))
) %>% t()
post_fix_high <- as.data.frame(model_GFR_GPL_mediate_high) %>%
select(b_GFRMDRD_Intercept, b_GFRMDRD_infliximab, b_GFRMDRD_DGF,
b_DGF_Intercept, b_DGF_infliximab) %>%
mutate(predicted_DGF_ctrl = inv_logit(b_DGF_Intercept),
predicted_DGF_infx = inv_logit(b_DGF_Intercept + b_DGF_infliximab)) %>%
mutate(
indirect_pred_ctrl = b_GFRMDRD_Intercept +
(b_GFRMDRD_infliximab * mean(data_imputed_highGPL$infliximab) ) +
(b_GFRMDRD_DGF * predicted_DGF_ctrl),
indirect_pred_infx = b_GFRMDRD_Intercept +
(b_GFRMDRD_infliximab * mean(data_imputed_highGPL$infliximab) ) +
(b_GFRMDRD_DGF * predicted_DGF_infx),
) %>%
mutate(
`Direct Effect (ADE)` = b_GFRMDRD_infliximab,
`Indirect Effect (ACME)` = indirect_pred_infx - indirect_pred_ctrl,
`Mediator Effect` = b_GFRMDRD_DGF,
`Total Effect` = (
(indirect_pred_infx - indirect_pred_ctrl) + b_GFRMDRD_infliximab
)
) %>%
select(`Direct Effect (ADE)`:`Total Effect`)
med_eff_high <- sapply(
post_fix_high,
function(p) quantile(p, probs = c(0.5, 0.025, 0.975))
) %>% t()
mediation_effect <- data.frame(
effect = rownames(med_eff_low),
`Low_aCL` = paste0(
round(c(med_eff_low[, 1]), 1),
' [',
round(c(med_eff_low[, 2]), 1),
', ',
round(c(med_eff_low[, 3]), 1),
']'
),
`High_aCL` = paste0(
round(c(med_eff_high[, 1]), 1),
' [',
round(c(med_eff_high[, 2]), 1),
', ',
round(c(med_eff_high[, 3]), 1),
']'
)
)Print table
Open code
kableExtra::kable(mediation_effect)ADE [95% credible interval]) estimates the direct effect of infliximab on eGFR, controlling for the indirect pathway via DGF and other covariates. The Average Causal Mediation Effect (ACME [95% credible interval]) quantifies the indirect effect via DGF. The Mediator Effect represents the effect of DGF on eGFR, adjusting for infliximab and other covariates. The Total Effect captures the overall impact of infliximab on eGFR, combining both direct and indirect pathways.
| effect | Low_aCL | High_aCL |
|---|---|---|
| Direct Effect (ADE) | 2.1 [-6.1, 10.1] | -11.1 [-19.1, -2.9] |
| Indirect Effect (ACME) | 5.4 [1.6, 10.6] | -2.3 [-6.6, 0.3] |
| Mediator Effect | -18.5 [-27, -9.9] | -12.3 [-20.9, -3.7] |
| Total Effect | 7.7 [-1, 16.1] | -13.6 [-22.1, -5.1] |
12 Models without large GPL_BC
Open code
infl_max <- max(data_first[which(data_first$infliximab == 1), 'GPL_BC_log2']); infl_max
## [1] 2.740331
ctrl_max <- max(data_first[which(data_first$infliximab == 0), 'GPL_BC_log2']); ctrl_max
## [1] 4.949819
data_sens <- data_first %>% filter(GPL_BC_log2 <= infl_max) %>%
mutate(group = factor(if_else(infliximab == 1, 'infliximab', 'control')))12.1 DGF by GPL_BC
12.1.1 Priors
Open code
# function to get prior
create_prior <- function(var, sigma, class = "b", coef = NULL) {
set_prior(paste0("normal(0, ", sigma, ")"), class = class, coef = coef)
}
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
2 / sd(data_sens$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
2 / sd(data_sens$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
2 / sd(data_sens$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
2 / sd(data_sens$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4,
coef = "male_sex"),
create_prior("perfusion_event",
4,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"),
create_prior("infliximab",
4,
coef = "infliximab"),
set_prior("student_t(3, 0, 0.6)", class = "sds",
coef = 's(GPL_BC_log2, bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 0.3)", class = "sds",
coef = 's(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", logit(mean(data_sens$DGF)), ", 10)"),
class = "Intercept")
)12.1.2 Model
Open code
model_dgf_GPL_BC_interaction_NL_sens <- run(
expr = brm(
DGF ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(GPL_BC_log2, bs = 'ps', k = 5) +
s(GPL_BC_log2, by = infliximab, bs = 'ps', k = 5),
family = bernoulli(),
data = data_sens,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 5000, warmup = 2000,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_dgf_GPL_BC_interaction_NL_sens",
reuse = TRUE
)
summary(model_dgf_GPL_BC_interaction_NL_sens, robust = TRUE)
## Family: bernoulli
## Links: mu = logit
## Formula: DGF ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(GPL_BC_log2, bs = "ps", k = 5) + s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)
## Data: data_sens (Number of observations: 170)
## Draws: 4 chains, each with iter = 5000; warmup = 2000; thin = 1;
## total post-warmup draws = 12000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sGPL_BC_log2_1) 0.45 0.40 0.02 1.88 1.00
## sds(sGPL_BC_log2infliximab_1) 0.22 0.21 0.01 1.07 1.00
## Bulk_ESS Tail_ESS
## sds(sGPL_BC_log2_1) 7041 5216
## sds(sGPL_BC_log2infliximab_1) 8954 5147
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Intercept -1.23 0.49 -2.25 -0.26 1.00 11736
## male_sex 1.15 0.41 0.35 1.99 1.00 12193
## Irec_ageM50 -0.01 0.02 -0.05 0.03 1.00 11702
## male_sex_donor 0.31 0.40 -0.45 1.11 1.00 10843
## IKDPIM50 0.00 0.01 -0.02 0.02 1.00 10691
## ICITM15 0.09 0.03 0.03 0.15 1.00 10923
## IHLA_MMM5 0.25 0.14 -0.01 0.52 1.00 10410
## perfusion_event -0.39 0.39 -1.17 0.39 1.00 11052
## infliximab 0.06 3.89 -7.58 7.58 1.00 3997
## sGPL_BC_log2_1 2.05 1.19 -0.39 4.66 1.00 7724
## sGPL_BC_log2:infliximab_1 1.65 2.73 -3.57 6.90 1.00 4254
## sGPL_BC_log2:infliximab_2 -2.09 1.33 -4.69 0.48 1.00 4694
## Tail_ESS
## Intercept 9635
## male_sex 9580
## Irec_ageM50 9522
## male_sex_donor 8929
## IKDPIM50 8477
## ICITM15 8949
## IHLA_MMM5 8917
## perfusion_event 9013
## infliximab 5974
## sGPL_BC_log2_1 6425
## sGPL_BC_log2:infliximab_1 6490
## sGPL_BC_log2:infliximab_2 6814
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_dgf_GPL_BC_interaction_NL_sens)
## prior class
## (flat) b
## normal(0, 0.281193624307594) b
## normal(0, 1.32489040521642) b
## normal(0, 0.0974514024084987) b
## normal(0, 4) b
## normal(0, 0.194443540354437) b
## normal(0, 4) b
## normal(0, 4) b
## normal(0, 4) b
## (flat) b
## (flat) b
## (flat) b
## normal(-0.658055860748675, 10) Intercept
## student_t(3, 0, 2.5) sds
## student_t(3, 0, 0.6) sds
## student_t(3, 0, 0.3) sds
## coef group resp dpar nlpar lb ub
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sGPL_BC_log2_1
## sGPL_BC_log2:infliximab_1
## sGPL_BC_log2:infliximab_2
##
## 0
## s(GPL_BC_log2, bs = "ps", k = 5) 0
## s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5) 0
## source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## default
## user
## user
tr2 <- round(exp(fixef(model_dgf_GPL_BC_interaction_NL_sens,
robust = TRUE)[-c(1,9:12), c(1,3,4)]), 2)
antibody_seq <- quantile(data_sens$GPL_BC_log2,
probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_dgf_GPL_BC_interaction_NL_sens,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get odds ratio for infliximab effect across antibody values
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_GPL_BC_log2_int <- quantile(
exp((log(prediction$p95) - log(prediction$p05))/scaling_unit),
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_GPL_BC_log2_int, 2))
row.names(tr2)[8] <- 'infliximab:GPL_BC_log2'
colnames(tr2)[1] <- '(R)OR'
kableExtra::kable(tr2)GPL_BC_log2) and infliximab treatment on delayed graft function (DGF), while accounting for other covariates, restricting the dataset to patients with anti-cardiolipin IgG levels within the range observed in the infliximab group. Effects are presented as odds ratios (OR), with the last row reporting the ratio of odds ratios (ROR). The ROR represents the estimated ratio of infliximab’s treatment effect at the 95th versus the 5th percentile of anti-cardiolipin IgG, quantifying the interaction effect.Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| (R)OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 3.16 | 1.43 | 7.31 |
| Irec_ageM50 | 0.99 | 0.95 | 1.03 |
| male_sex_donor | 1.36 | 0.64 | 3.04 |
| IKDPIM50 | 1.00 | 0.98 | 1.02 |
| ICITM15 | 1.09 | 1.03 | 1.16 |
| IHLA_MMM5 | 1.28 | 0.99 | 1.68 |
| perfusion_event | 0.68 | 0.31 | 1.47 |
| infliximab:GPL_BC_log2 | 49.76 | 4.11 | 715.86 |
12.1.3 Visualisation - penalized non-linear effect
Extract posterior draws
Open code
antibody_perc <- quantile(data_sens$GPL_BC_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_dgf_GPL_BC_interaction_NL_sens,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
GPL_BC_log2 = data_prediction$GPL_BC_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control"))) %>%
ggplot(aes(x = GPL_BC_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 1),
breaks = c(seq(0, 1, by = 0.2))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
labs(x = expression(log[2]~"(aCL IgG ["*mu*"g/ml])"), y = "DGF risk") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_rug(
data = data_sens %>% filter(DGF == 0),
aes(x = GPL_BC_log2),
sides = "b",
color = "black",
size = 0.12,
inherit.aes = FALSE
) +
geom_rug(
data = data_sens %>% filter(DGF == 1),
aes(x = GPL_BC_log2),
sides = "t",
color = "black",
linewidth = 0.12,
inherit.aes = FALSE
) +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -3.861561 2.740331
tr <- posterior_epred(
model_dgf_GPL_BC_interaction_NL_sens,
newdata = data_prediction)
tr_ctrl <- (logit(tr[,c(ncol(tr)/2)]) - logit(tr[,c(1)])) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (logit(tr[,c(ncol(tr))]) - logit(tr[,c(ncol(tr)/2)+1]))/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_GPL_BC_log2 = tr_ctrl,
b_GPL_BC_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = exp(b_GPL_BC_log2),
infliximab = exp(b_GPL_BC_log2_infliximab)) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(1)
CIS
## control infliximab
## 2.5% 0.4 1.0
## 97.5% 1.0 2.8
## 50% 0.6 1.7
## 0.1% 0.3 0.7
## 99.9% 1.3 4.0
xpos <- 10
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aCL IgG on DGF risk (OR))",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(1/20, 20)) +
scale_x_continuous(transform = 'log2',
breaks = c(1/16, 1/4, 1, 4 ,16),
labels = c("1/16", "1/4", "1", "4", "16")) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 240
xseq <- c(1/64, 1/8, 1, 8, 64, 512)
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
antibody_seq
## 5% 25% 50% 75% 95%
## -1.8017117 -0.7949708 -0.1340217 0.6308746 2.0711263
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_dgf_GPL_BC_interaction_NL_sens,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
(prediction_infliximab/(1-prediction_infliximab))/
(prediction_ctrl/(1-prediction_ctrl))
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## p05 p25 p50 p75 p95
## 2.5% 0.02 0.11 0.26 0.54 1.21
## 97.5% 0.46 0.74 1.23 2.93 27.34
## 50% 0.11 0.30 0.58 1.26 5.61
## 0.1% 0.01 0.06 0.16 0.33 0.50
## 99.9% 1.08 1.29 1.89 4.75 66.13
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'GPL_BC_percentile') %>%
ggplot(aes(y = GPL_BC_percentile, x = value, fill = GPL_BC_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on DGF risk (odds ratio)",
y = 'Percentile of aCL IgG value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(1/300, 1150)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
scale_x_continuous(transform = 'log2',
breaks = c(xseq),
labels = c("1/64", "1/8", "1", "8", "64", '512')) +
geom_vline(xintercept = 1, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Odds ratio: ", CIS[3,5]),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Odds ratio: ", CIS[3,4]),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Odds ratio: ", CIS[3,3]),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Odds ratio: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Odds ratio: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", CIS[1,5], ", ", CIS[2,5], "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", CIS[1,4], ", ", CIS[2,4], "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", CIS[1,3], ", ", CIS[2,3], "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) 12.1.3.1 Figure merged
Open code
plotac <- "sup_figure_2"
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}12.2 GFR by GPL_BC
12.2.1 Prior
Open code
priors_interaction_pnl <- c(
create_prior("Irec_ageM50",
(2*GFR_sd) / sd(data_sens$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"),
create_prior("IHLA_MMM5",
(2*GFR_sd) / sd(data_sens$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"),
create_prior("IKDPIM50",
(2*GFR_sd) / sd(data_sens$KDPI, na.rm = TRUE),
coef = "IKDPIM50"),
create_prior("ICITM15",
(2*GFR_sd) / sd(data_sens$CIT, na.rm = TRUE),
coef = "ICITM15"),
create_prior("male_sex",
4*GFR_sd,
coef = "male_sex"),
create_prior("perfusion_event",
4*GFR_sd,
coef = "perfusion_event"),
create_prior("male_sex_donor",
4*GFR_sd,
coef = "male_sex_donor"),
create_prior("infliximab",
4*GFR_sd,
coef = "infliximab"),
set_prior("student_t(3, 0, 12)", class = "sds",
coef = 's(GPL_BC_log2, bs = "ps", k = 5)'),
set_prior("student_t(3, 0, 6)", class = "sds",
coef = 's(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)'),
set_prior(paste0("normal(", mean(data_sens$GFR_MDRD), ", 200)"),
class = "Intercept")
)12.2.2 Model
Open code
model_GFR_MDRD_GPL_BC_interaction_NL_sens <- run(
expr = brm(
GFR_MDRD ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
s(GPL_BC_log2, bs = 'ps', k = 5) +
s(GPL_BC_log2, by = infliximab, bs = 'ps', k = 5),
family = student(),
data = data_sens,
prior = priors_interaction_pnl,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 5000, warmup = 2000,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_GFR_MDRD_GPL_BC_interaction_NL_sens",
reuse = TRUE
)
summary(model_GFR_MDRD_GPL_BC_interaction_NL_sens, robust = TRUE)
## Family: student
## Links: mu = identity; sigma = identity; nu = identity
## Formula: GFR_MDRD ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + s(GPL_BC_log2, bs = "ps", k = 5) + s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5)
## Data: data_sens (Number of observations: 170)
## Draws: 4 chains, each with iter = 5000; warmup = 2000; thin = 1;
## total post-warmup draws = 12000
##
## Smoothing Spline Hyperparameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat
## sds(sGPL_BC_log2_1) 10.75 6.61 1.51 34.13 1.00
## sds(sGPL_BC_log2infliximab_1) 3.91 3.54 0.16 18.11 1.00
## Bulk_ESS Tail_ESS
## sds(sGPL_BC_log2_1) 5999 4257
## sds(sGPL_BC_log2infliximab_1) 10958 5581
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## Intercept 56.12 3.74 48.82 63.48 1.00 14100
## male_sex -3.07 3.18 -9.31 3.20 1.00 17270
## Irec_ageM50 0.04 0.15 -0.25 0.34 1.00 16383
## male_sex_donor -1.29 3.09 -7.32 4.89 1.00 15270
## IKDPIM50 -0.18 0.08 -0.34 -0.02 1.00 14260
## ICITM15 0.28 0.21 -0.14 0.69 1.00 17187
## IHLA_MMM5 -1.51 1.04 -3.57 0.57 1.00 14539
## perfusion_event -5.95 3.21 -12.23 0.30 1.00 17005
## infliximab 0.77 77.45 -153.15 155.03 1.00 4930
## sGPL_BC_log2_1 -15.85 13.41 -47.71 15.01 1.00 9497
## sGPL_BC_log2:infliximab_1 -9.84 53.57 -113.60 95.89 1.00 5056
## sGPL_BC_log2:infliximab_2 8.10 22.49 -36.47 52.92 1.00 4949
## Tail_ESS
## Intercept 10099
## male_sex 8274
## Irec_ageM50 9260
## male_sex_donor 8994
## IKDPIM50 9179
## ICITM15 8812
## IHLA_MMM5 9027
## perfusion_event 9245
## infliximab 6673
## sGPL_BC_log2_1 7594
## sGPL_BC_log2:infliximab_1 7007
## sGPL_BC_log2:infliximab_2 6600
##
## Further Distributional Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 17.96 1.19 15.64 20.35 1.00 12286 8340
## nu 20.08 10.94 6.86 57.49 1.00 13817 8404
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_GFR_MDRD_GPL_BC_interaction_NL_sens)
## prior class
## (flat) b
## normal(0, 5.69629817247165) b
## normal(0, 26.8390537393692) b
## normal(0, 1.9741281361241) b
## normal(0, 81.0302607180105) b
## normal(0, 3.93895269246326) b
## normal(0, 81.0302607180105) b
## normal(0, 81.0302607180105) b
## normal(0, 81.0302607180105) b
## (flat) b
## (flat) b
## (flat) b
## normal(51.1962352941176, 200) Intercept
## gamma(2, 0.1) nu
## student_t(3, 0, 18.1) sds
## student_t(3, 0, 12) sds
## student_t(3, 0, 6) sds
## student_t(3, 0, 18.1) sigma
## coef group resp dpar nlpar lb ub
##
## ICITM15
## IHLA_MMM5
## IKDPIM50
## infliximab
## Irec_ageM50
## male_sex
## male_sex_donor
## perfusion_event
## sGPL_BC_log2_1
## sGPL_BC_log2:infliximab_1
## sGPL_BC_log2:infliximab_2
##
## 1
## 0
## s(GPL_BC_log2, bs = "ps", k = 5) 0
## s(GPL_BC_log2, by = infliximab, bs = "ps", k = 5) 0
## 0
## source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## (vectorized)
## (vectorized)
## (vectorized)
## user
## default
## default
## user
## user
## default
tr2 <- round(fixef(model_GFR_MDRD_GPL_BC_interaction_NL_sens,
robust = TRUE)[-c(1,9:12), c(1,3,4)], 2)
antibody_seq <- quantile(data_sens$GPL_BC_log2,
probs = c(0.05, 0.95))
asl <- length(antibody_seq)
quant_dif <- antibody_seq[2] - antibody_seq[1]
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL_sens,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
## get Estimate for infliximab effect across antibody values
prediction <- (
prediction_infliximab-
prediction_ctrl
) %>% data.frame()
names(prediction) <- c('p05', 'p95')
infliximab_GPL_BC_log2_int <- quantile(
(prediction$p95 - prediction$p05)/scaling_unit,
probs = c(0.5, 1/40, 39/40))
tr2 <- rbind(tr2, round(infliximab_GPL_BC_log2_int, 2))
row.names(tr2)[8] <- 'infliximab:GPL_BC_log2'
kableExtra::kable(tr2)GPL_BC_log2) and infliximab treatment on estimated glomerular filtration rate (eGFR, GFR_MDRD), after excluding patients with anti-cardiolipin IgG levels above the maximum in the IFX group and while accounting for other covariates. Estimate represents the estimated change in eGFR per one-unit increase in the predictor. The last row (infliximab:GPL_BC_log2) reports the difference in infliximab’s treatment effect at the 95th versus the 5th percentile of anti-cardiolipin IgG, quantifying the interaction effect. Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| Estimate | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | -3.07 | -9.31 | 3.20 |
| Irec_ageM50 | 0.04 | -0.25 | 0.34 |
| male_sex_donor | -1.29 | -7.32 | 4.89 |
| IKDPIM50 | -0.18 | -0.34 | -0.02 |
| ICITM15 | 0.28 | -0.14 | 0.69 |
| IHLA_MMM5 | -1.51 | -3.57 | 0.57 |
| perfusion_event | -5.95 | -12.23 | 0.30 |
| infliximab:GPL_BC_log2 | -18.27 | -36.99 | 0.59 |
12.2.3 Visualisation - penalized non-linear effect
Extract posterior draws
Open code
antibody_perc <- quantile(data_sens$GPL_BC_log2,
probs = c(0, 0.02, 0.05, 0.25, 0.5, 0.75, 0.95, 0.98, 1))
antibody_seq <- seq(antibody_perc[1],
antibody_perc[length(antibody_perc)],
length.out = 101)
## create prediction
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
prediction <- data.frame(
posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL_sens,
newdata = data_prediction) %>% posterior_summary(
robust = TRUE
) %>% data.frame() %>% select(-Est.Error),
group = factor(if_else(data_prediction$infliximab == 1, 'infliximab', 'control')),
GPL_BC_log2 = data_prediction$GPL_BC_log2)Figure A
Open code
cole <- c('#CD7006', '#0028F0')
fig_a <- prediction %>%
mutate(group = factor(group, levels = c("infliximab", "control")),
`Q2.5` = if_else(`Q2.5` < 0, 0, `Q2.5`)) %>%
ggplot(aes(x = GPL_BC_log2, y = Estimate, col = group, fill = group)) +
geom_line(aes(y = Estimate), linewidth = 1) +
scale_y_continuous(limits = c(0, 125),
breaks = c(seq(0, 125, by = 25))) +
geom_ribbon(aes(ymin = `Q2.5`, ymax = `Q97.5`),
alpha = 0.4, color = NA) +
geom_point(data = data_sens,
aes(x = GPL_BC_log2, y = GFR_MDRD, col = group, fill = group)) +
labs(x = expression(log[2]~"(aCL IgG ["*mu*"g/ml])"),
y = "GFR (mL/min/1.73 m²)") +
scale_color_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_fill_manual(values = cole,
name = "group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
facet_grid(rows = vars(group)) +
theme(axis.text=element_text(size = 10),
axis.title=element_text(size = 12),
strip.text.x = element_text(size = 12),
legend.position = "none") +
geom_vline(xintercept = antibody_perc[3:7], linetype = 2,
color = "grey50", size = 0.3)Figure B
Open code
antibody_seq <- antibody_perc[c(1, 9)]
antibody_seq
## 0% 100%
## -3.861561 2.740331
tr <- posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL_sens,
newdata = data_prediction)
tr_ctrl <- (tr[,c(ncol(tr)/2)] - tr[,c(1)]) /
(antibody_seq[2] - antibody_seq[1])
tr_infliximab <- (tr[,c(ncol(tr))] - tr[,c(ncol(tr)/2)+1])/
(antibody_seq[2] - antibody_seq[1])
post_fix <- data.frame(
b_GPL_BC_log2 = tr_ctrl,
b_GPL_BC_log2_infliximab = tr_infliximab
)
tr <- post_fix %>%
mutate(control = b_GPL_BC_log2,
infliximab = b_GPL_BC_log2_infliximab) %>%
select(control, infliximab) %>%
data.frame()
CIS <- sapply(
tr,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(2)
CIS
## control infliximab
## 2.5% -0.21 -5.28
## 97.5% 7.41 3.26
## 50% 3.55 -1.13
## 0.1% -2.41 -7.46
## 99.9% 9.61 6.03
xpos <- 20
fig_b <- tr %>%
pivot_longer(values_to = 'value',
cols = c('control', 'infliximab'),
names_to = 'group') %>%
ggplot(aes(x = value, y = group, fill = group)) +
stat_halfeye(.width = c(0.95), slab_alpha=0.5,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of doubling aCL IgG on GFR (mL/min/1.73 m²) ",
y = 'Treatment group') +
scale_fill_manual(values = cole,
name = "Treatment group",
breaks = c('control', 'infliximab'),
labels = c('control', 'infliximab')) +
scale_y_discrete(expand = expansion(add = 0.1)) +
coord_cartesian(xlim = c(-20, 26)) +
geom_vline(xintercept = 0, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 2.85 ,
label = paste0("Estimate: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85 ,
label = paste0("Estimate: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 2.6 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.6 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) Figure C
Open code
cole <- c("#8B4789", "#8B5F77", "#8B7765", "#6F815C", "#548B54")
xpos <- 30
antibody_seq <- antibody_perc[c(3, 4, 5, 6, 7)]
asl <- length(antibody_seq)
data_prediction <- data.frame(
male_sex = rep(mmale_sex, 2*length(antibody_seq)),
`male_sex_donor` = rep(mmale_sex_donor, 2*length(antibody_seq)),
`perfusion_event` = rep(mperfusion_event, 2*length(antibody_seq)),
`infliximab` = c(rep(0, length(antibody_seq)), rep(1, length(antibody_seq))),
`rec_age` = rep(mrec_age, 2*length(antibody_seq)),
`KDPI` = rep(mKDPI, 2*length(antibody_seq)),
`CIT` = rep(mCIT, 2*length(antibody_seq)),
`HLA_MM` = rep(mHLA_MM, 2*length(antibody_seq)),
`GPL_BC_log2` = c(antibody_seq, antibody_seq)
)
tr <- posterior_epred(
model_GFR_MDRD_GPL_BC_interaction_NL_sens,
newdata = data_prediction)
prediction_ctrl <- tr[, c(1:asl)]
prediction_infliximab <- tr[, c((asl+1):(asl*2))]
prediction <- (
prediction_infliximab-
prediction_ctrl
) %>% data.frame()
names(prediction) <- c('p05', 'p25', 'p50', 'p75', 'p95')
CIS <- sapply(
prediction,
function(p) quantile(p, probs = c(1/40, 39/40, 0.5, 1e-3, 1-1e-3))
) %>%
round(1)
CIS
## p05 p25 p50 p75 p95
## 2.5% -3.9 -5.3 -7.5 -11.8 -24.1
## 97.5% 17.4 8.9 4.8 1.8 0.7
## 50% 6.7 1.9 -1.3 -5.0 -11.7
## 0.1% -10.6 -9.0 -11.2 -15.8 -30.5
## 99.9% 24.2 13.6 8.8 6.1 8.5
fig_c <- prediction %>%
pivot_longer(values_to = 'value',
cols = c('p05', 'p25', 'p50', 'p75', 'p95'),
names_to = 'GPL_BC_percentile') %>%
ggplot(aes(y = GPL_BC_percentile, x = value, fill = GPL_BC_percentile)) +
stat_halfeye(.width = c(0.95), slab_alpha = 0.55,
linewidth = 5,
shape = 18,
point_size = 5,
normalize = "groups",
p_limits = c(1e-3, 1-1e-3)) +
labs(x = "Effect of infliximab on GFR (mL/min/1.73 m²)",
y = 'Percentile of aCL IgG value') +
scale_fill_manual(values = cole,
name = "Percentile of aCL IgG value",
breaks = c('p05', 'p25', 'p50', 'p75', 'p95'),
labels = c('p05', 'p25', 'p50', 'p75', 'p95')) +
coord_cartesian(xlim = c(-40, 40)) +
scale_y_discrete(expand = expansion(add = 0.1)) +
geom_vline(xintercept = 0, linetype = 2,
color = "red", size = 0.6) +
theme(axis.text = element_text(size = 12),
axis.title = element_text(size = 12)) +
theme(legend.position = "none") +
annotate("text", x = xpos, y = 5.85 ,
label = paste0("Estimate: ", CIS[3,5]),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.85,
label = paste0("Estimate: ", CIS[3,4]),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.85,
label = paste0("Estimate: ", CIS[3,3]),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.85,
label = paste0("Estimate: ", CIS[3,2]),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.85,
label = paste0("Estimate: ", CIS[3,1]),
color = cole[1] ) +
annotate("text", x = xpos, y = 5.5 ,
label = paste0("95% CI: [", CIS[1,5], ", ", CIS[2,5], "]"),
color = cole[5] ) +
annotate("text", x = xpos, y = 4.5 ,
label = paste0("95% CI: [", CIS[1,4], ", ", CIS[2,4], "]"),
color = cole[4] ) +
annotate("text", x = xpos, y = 3.5 ,
label = paste0("95% CI: [", CIS[1,3], ", ", CIS[2,3], "]"),
color = cole[3] ) +
annotate("text", x = xpos, y = 2.5 ,
label = paste0("95% CI: [", CIS[1,2], ", ", CIS[2,2], "]"),
color = cole[2] ) +
annotate("text", x = xpos, y = 1.5 ,
label = paste0("95% CI: [", CIS[1,1], ", ", CIS[2,1], "]"),
color = cole[1] ) 12.2.3.1 Figure merged
Open code
plotac <- 'sup_figure_6'
path <- "gitignore/figures"
fig <- cowplot::plot_grid(fig_b, fig_c,
rel_heights = c(0.7, 1),
labels = c("B", "C"),
ncol = 1
)
assign(
plotac,
cowplot::plot_grid(
fig_a, fig,
rel_widths = c(0.6, 1),
labels = c("A", "")
)
)
get(plotac)
if (file.exists(paste0(path, "/", plotac, ".pdf")) == FALSE) {
ggsave(
path = paste0(path),
filename = plotac,
device = "pdf",
width = 9,
height = 6
)
}13 DGF Subgroup analysis by GPL_BC
We will use data divided to patients with under- and above-median value of aCL IgG (GPL_BC)
13.1 Define priors
Open code
priors_subset <- c(
create_prior("GPL_BC_log2",
2 / sd(data_model_priorImpute$GPL_BC_log2, na.rm = TRUE),
coef = "GPL_BC_log2"
),
create_prior("IHLA_MMM5",
2 / sd(data_model_priorImpute$HLA_MM, na.rm = TRUE),
coef = "IHLA_MMM5"
),
create_prior("IKDPIM50",
2 / sd(data_model_priorImpute$KDPI, na.rm = TRUE),
coef = "IKDPIM50"
),
create_prior("Irec_ageM50",
2 / sd(data_model_priorImpute$rec_age, na.rm = TRUE),
coef = "Irec_ageM50"
),
create_prior("ICITM15",
2 / sd(data_model_priorImpute$CIT, na.rm = TRUE),
coef = "ICITM15"
),
create_prior("male_sex",
4,
coef = "male_sex"
),
create_prior("perfusion_event",
4,
coef = "perfusion_event"
),
create_prior("male_sex_donor",
4,
coef = "male_sex_donor"
),
create_prior("infliximab",
4,
coef = "infliximab"
),
set_prior(paste0("normal(", logit(mean(data_model_priorImpute$DGF)), ", 10)"),
class = "Intercept"
)
)13.2 Fit model for \(<\) median aCL IgG level
Open code
model_dgf_GPL_BC_lowGPLBC <- run(
expr = brm(
DGF ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
GPL_BC_log2,
family = bernoulli(),
data = data_imputed_lowGPL,
prior = priors_subset,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 4000, warmup = 2000,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_dgf_GPL_BC_lowGPLBC",
reuse = TRUE
)
summary(model_dgf_GPL_BC_lowGPLBC, robust = TRUE)
## Family: bernoulli
## Links: mu = logit
## Formula: DGF ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + GPL_BC_log2
## Data: data_imputed_lowGPL (Number of observations: 88)
## Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
## total post-warmup draws = 8000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept -1.15 0.88 -2.92 0.57 1.00 6103 5642
## male_sex 0.66 0.61 -0.50 1.88 1.00 7547 5709
## Irec_ageM50 -0.00 0.03 -0.05 0.05 1.00 7614 6063
## male_sex_donor 0.63 0.56 -0.53 1.77 1.00 7908 5889
## IKDPIM50 0.00 0.01 -0.03 0.03 1.00 6795 5914
## ICITM15 0.08 0.04 -0.00 0.16 1.00 7322 6440
## IHLA_MMM5 0.26 0.20 -0.12 0.67 1.00 6960 6236
## perfusion_event -0.43 0.58 -1.61 0.69 1.00 7869 6343
## infliximab -1.55 0.57 -2.74 -0.45 1.00 6379 5667
## GPL_BC_log2 -0.49 0.35 -1.22 0.18 1.00 7280 6096
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_dgf_GPL_BC_lowGPLBC)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 1.41170525720746) b GPL_BC_log2
## normal(0, 0.280307006032291) b ICITM15
## normal(0, 1.38219051128263) b IHLA_MMM5
## normal(0, 0.0970980394231448) b IKDPIM50
## normal(0, 4) b infliximab
## normal(0, 0.190589762164436) b Irec_ageM50
## normal(0, 4) b male_sex
## normal(0, 4) b male_sex_donor
## normal(0, 4) b perfusion_event
## normal(-0.667829372575656, 10) Intercept
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
tr <- round(exp(fixef(model_dgf_GPL_BC_lowGPLBC, robust = TRUE)[-1, c(1,3,4)]), 2)
colnames(tr)[1] <- 'OR'
kableExtra::kable(tr)infliximab treatment and log2-transformed anti-cardiolipin IgG (GPL_BC_log2), on delayed graft function (DGF), without interaction terms and including only patients with anti-cardiolipin IgG level below median. The odds ratio (OR) represents the estimated change in the odds of DGF per one-unit increase in the predictor. OR: odds ratio; Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| OR | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 1.94 | 0.61 | 6.59 |
| Irec_ageM50 | 1.00 | 0.95 | 1.05 |
| male_sex_donor | 1.87 | 0.59 | 5.88 |
| IKDPIM50 | 1.00 | 0.97 | 1.03 |
| ICITM15 | 1.08 | 1.00 | 1.18 |
| IHLA_MMM5 | 1.30 | 0.89 | 1.96 |
| perfusion_event | 0.65 | 0.20 | 2.00 |
| infliximab | 0.21 | 0.06 | 0.64 |
| GPL_BC_log2 | 0.61 | 0.29 | 1.20 |
13.3 Fit model for aCL \(\geq\) median
Open code
model_dgf_GPL_BC_highGPLBC <- run(
expr = brm(
DGF ~
male_sex +
I(rec_age - 50) +
male_sex_donor +
I(KDPI - 50) +
I(CIT - 15) +
I(HLA_MM - 5) +
perfusion_event +
infliximab +
GPL_BC_log2,
family = bernoulli(),
data = data_imputed_highGPL,
prior = priors_subset,
backend = "cmdstanr",
seed = 2025,
cores = 4, chains = 4,
iter = 4000, warmup = 2000,
control = list(adapt_delta = 0.95)
),
path = "gitignore/run/model_dgf_GPL_BC_highGPLBC",
reuse = TRUE
)
summary(model_dgf_GPL_BC_highGPLBC, robust = TRUE)
## Family: bernoulli
## Links: mu = logit
## Formula: DGF ~ male_sex + I(rec_age - 50) + male_sex_donor + I(KDPI - 50) + I(CIT - 15) + I(HLA_MM - 5) + perfusion_event + infliximab + GPL_BC_log2
## Data: data_imputed_highGPL (Number of observations: 89)
## Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
## total post-warmup draws = 8000
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept -2.17 0.82 -3.90 -0.66 1.00 5958 5518
## male_sex 1.56 0.59 0.44 2.78 1.00 6964 5785
## Irec_ageM50 -0.04 0.02 -0.09 0.01 1.00 7544 6006
## male_sex_donor 0.31 0.58 -0.82 1.46 1.00 7261 6549
## IKDPIM50 0.02 0.01 -0.00 0.05 1.00 6958 6417
## ICITM15 0.08 0.04 0.01 0.16 1.00 7101 5523
## IHLA_MMM5 0.33 0.20 -0.05 0.74 1.00 6725 5730
## perfusion_event -0.96 0.61 -2.22 0.20 1.00 6888 5602
## infliximab 1.06 0.55 0.00 2.16 1.00 7743 6408
## GPL_BC_log2 0.33 0.25 -0.16 0.84 1.00 7068 6138
##
## Draws were sampled using sample(hmc). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
prior_summary(model_dgf_GPL_BC_highGPLBC)
## prior class coef group resp dpar nlpar
## (flat) b
## normal(0, 1.41170525720746) b GPL_BC_log2
## normal(0, 0.280307006032291) b ICITM15
## normal(0, 1.38219051128263) b IHLA_MMM5
## normal(0, 0.0970980394231448) b IKDPIM50
## normal(0, 4) b infliximab
## normal(0, 0.190589762164436) b Irec_ageM50
## normal(0, 4) b male_sex
## normal(0, 4) b male_sex_donor
## normal(0, 4) b perfusion_event
## normal(-0.667829372575656, 10) Intercept
## lb ub source
## default
## user
## user
## user
## user
## user
## user
## user
## user
## user
## user
tr <- round(exp(fixef(model_dgf_GPL_BC_highGPLBC, robust = TRUE)[-1, c(1,3,4)]), 3)
colnames(tr)[1] <- 'Odds ratio'
kableExtra::kable(tr)infliximab treatment and log2-transformed anti-cardiolipin IgG (GPL_BC_log2), on delayed graft function (DGF), without interaction terms and including only patients with anti-cardiolipin IgG level at/above median. The odds ratio (OR) represents the estimated change in the odds of DGF per one-unit increase in the predictor. OR: odds ratio; Q2.5 and Q97.5: lower and upper bounds of the 95% credible interval, respectively.
| Odds ratio | Q2.5 | Q97.5 | |
|---|---|---|---|
| male_sex | 4.754 | 1.548 | 16.143 |
| Irec_ageM50 | 0.964 | 0.918 | 1.012 |
| male_sex_donor | 1.361 | 0.440 | 4.314 |
| IKDPIM50 | 1.024 | 0.996 | 1.055 |
| ICITM15 | 1.083 | 1.008 | 1.179 |
| IHLA_MMM5 | 1.387 | 0.950 | 2.098 |
| perfusion_event | 0.382 | 0.108 | 1.218 |
| infliximab | 2.897 | 1.005 | 8.695 |
| GPL_BC_log2 | 1.397 | 0.855 | 2.324 |
14 Tables and Figures: list with links
14.1 Figures
Figure 1: data distributions across groups
Supplementary Figure 1: Spearman correlations
Figure 2: DGF risk according to infliximab:aCL IgG non-linear interaction.
Supplementary Figure 2: DGF risk according to infliximab:aCL IgG non-linear interaction but after excluding the patients with large aCL IgG values
Supplementary Figure 3: DGF risk according to infliximab:aCL IgM non-linear interaction
Supplementary Figure 4: eGFR according to infliximab:aCL IgG non-linear interaction
Supplementary Figure 5: eGFR according to infliximab:aCL IgM non-linear interaction
Supplementary Figure 6: eGFRaccording to infliximab:aCL IgG non-linear interaction but after excluding the patients with large aCL IgG values
Supplementary Figure 7: infection risk according to infliximab:aPE-dep IgG non-linear interaction.
Supplementary Figure 8: infection risk according to infliximab:aPE-ind IgG non-linear interaction.
14.2 Tables
Supplementary Table 1: demography stratified by treatment
Supplementary Table 1 - alternative: demography stratified by treatment and aCL IgG levls (below and at/above median)
Supplementary Table 3: post-transplant outcomes by treatment
Supplementary Table 4: unadjusted effect of different variables on DGF
Table 1: IFX x nAb non-linear interaction effects based on Bayesian multivariable models
Supplementary Table 5: unadjusted effect of different variables on eGFR
Supplementary Table 6: mediation analysis
Supplementary Table 7: unadjusted effect of different variables on infection risk
Supplementary Table 8: unadjusted effect of different variables on BKV infection
15 Reproducibility
Open code
sessionInfo()
## R version 4.4.3 (2025-02-28)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 22.04.5 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=cs_CZ.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=cs_CZ.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=cs_CZ.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=cs_CZ.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Europe/Prague
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] bayestestR_0.14.0 mice_3.17.0 ggbeeswarm_0.6.0 quantreg_5.98
## [5] SparseM_1.81 coxed_0.3.3 survival_3.7-0 rms_6.8-1
## [9] Hmisc_5.1-3 bayesplot_1.8.1 ggdist_3.3.2 kableExtra_1.4.0
## [13] lubridate_1.8.0 corrplot_0.92 arm_1.12-2 lme4_1.1-35.5
## [17] MASS_7.3-64 janitor_2.2.0 projpred_2.0.2 brms_2.21.0
## [21] Rcpp_1.0.13 glmnet_4.1-8 Matrix_1.7-0 boot_1.3-31
## [25] cowplot_1.1.1 pROC_1.18.0 mgcv_1.9-1 nlme_3.1-167
## [29] openxlsx_4.2.5 flextable_0.9.6 sjPlot_2.8.16 RJDBC_0.2-10
## [33] rJava_1.0-6 DBI_1.1.2 car_3.1-2 carData_3.0-5
## [37] skimr_2.1.5 gtsummary_2.0.2 emmeans_1.10.4 ggpubr_0.4.0
## [41] stringi_1.7.6 forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4
## [45] purrr_1.0.2 readr_2.1.2 tidyr_1.3.1 tibble_3.2.1
## [49] ggplot2_3.5.1 tidyverse_1.3.1
##
## loaded via a namespace (and not attached):
## [1] fs_1.6.4 matrixStats_1.3.0 httr_1.4.2
## [4] insight_0.20.2 repr_1.1.7 tools_4.4.3
## [7] backports_1.5.0 sjlabelled_1.2.0 utf8_1.2.4
## [10] R6_2.5.1 jomo_2.7-3 withr_3.0.1
## [13] Brobdingnag_1.2-7 prettyunits_1.1.1 gridExtra_2.3
## [16] cli_3.6.3 textshaping_0.3.6 performance_0.12.2
## [19] gt_0.11.0 officer_0.6.6 sandwich_3.0-1
## [22] labeling_0.4.2 sass_0.4.9 mvtnorm_1.1-3
## [25] polspline_1.1.25 ggridges_0.5.3 askpass_1.1
## [28] QuickJSR_1.3.1 systemfonts_1.0.4 commonmark_1.9.1
## [31] StanHeaders_2.32.10 foreign_0.8-88 gfonts_0.2.0
## [34] svglite_2.1.3 readxl_1.3.1 rstudioapi_0.16.0
## [37] httpcode_0.3.0 generics_0.1.3 shape_1.4.6
## [40] distributional_0.4.0 zip_2.2.0 inline_0.3.19
## [43] loo_2.4.1 fansi_1.0.6 abind_1.4-5
## [46] lifecycle_1.0.4 multcomp_1.4-18 yaml_2.3.5
## [49] snakecase_0.11.1 grid_4.4.3 promises_1.2.0.1
## [52] crayon_1.5.0 mitml_0.4-3 lattice_0.22-5
## [55] haven_2.4.3 pillar_1.9.0 knitr_1.48
## [58] estimability_1.5.1 codetools_0.2-19 pan_1.6
## [61] glue_1.7.0 V8_4.4.2 fontLiberation_0.1.0
## [64] data.table_1.15.4 vctrs_0.6.5 cellranger_1.1.0
## [67] gtable_0.3.0 assertthat_0.2.1 datawizard_0.12.2
## [70] xfun_0.46 mime_0.12 coda_0.19-4
## [73] iterators_1.0.14 ellipsis_0.3.2 TH.data_1.1-0
## [76] fontquiver_0.2.1 rstan_2.32.6 tensorA_0.36.2.1
## [79] vipor_0.4.5 rpart_4.1.24 colorspace_2.0-2
## [82] nnet_7.3-20 tidyselect_1.2.1 processx_3.8.4
## [85] compiler_4.4.3 curl_4.3.2 rvest_1.0.2
## [88] htmlTable_2.4.0 xml2_1.3.3 fontBitstreamVera_0.1.1
## [91] posterior_1.6.0 checkmate_2.3.2 scales_1.3.0
## [94] callr_3.7.6 digest_0.6.37 minqa_1.2.4
## [97] rmarkdown_2.27 htmltools_0.5.8.1 pkgconfig_2.0.3
## [100] base64enc_0.1-3 dbplyr_2.1.1 fastmap_1.2.0
## [103] rlang_1.1.4 htmlwidgets_1.6.4 shiny_1.9.1
## [106] farver_2.1.0 zoo_1.8-9 jsonlite_1.8.8
## [109] magrittr_2.0.3 Formula_1.2-4 munsell_0.5.0
## [112] gdtools_0.3.7 plyr_1.8.6 pkgbuild_1.3.1
## [115] parallel_4.4.3 sjmisc_2.8.10 ggeffects_1.7.0
## [118] splines_4.4.3 hms_1.1.1 sjstats_0.19.0
## [121] ps_1.7.7 uuid_1.0-3 ggsignif_0.6.3
## [124] markdown_1.13 reshape2_1.4.4 stats4_4.4.3
## [127] rstantools_2.1.1 crul_1.5.0 reprex_2.0.1
## [130] evaluate_1.0.0 RcppParallel_5.1.8 modelr_0.1.8
## [133] nloptr_2.0.0 tzdb_0.2.0 foreach_1.5.2
## [136] httpuv_1.6.5 MatrixModels_0.5-3 cards_0.2.2
## [139] openssl_1.4.6 cardx_0.2.1 broom_1.0.6
## [142] xtable_1.8-4 rstatix_0.7.0 later_1.3.0
## [145] viridisLite_0.4.0 ragg_1.2.1 beeswarm_0.4.0
## [148] cluster_2.1.8 gamm4_0.2-6 cmdstanr_0.8.0.9000
## [151] bridgesampling_1.1-2